Xác định thư mục nằm trên thiết bị nào


49

Nếu tôi làm

# cd /
# ln -s /home test
# cd test
# mount --bind $PWD /mnt

mục trong /proc/mounts

/dev/sda2 /mnt ext4 rw,noatime,data=ordered 0 0

đó là thiết bị được gắn vào /homevà không dễ dàng suy ra từ $PWDđó /test. Làm cách nào tôi có thể xác định thiết bị nào (tức là / dev / sda2) sẽ hiển thị /proc/mountsnói chung với điều kiện gắn kết có thể là một thư mục / tệp có khả năng bị "che khuất" bởi các liên kết tượng trưng, ​​các liên kết gắn kết khác, v.v.?

Câu trả lời:


49

Nếu tôi hiểu câu hỏi của bạn, bạn muốn biết thiết bị nào đã được sử dụng cho một giá treo nhất định. Đối với điều này, bạn có thể sử dụng dflệnh:

$ df -h 
Filesystem                         Size  Used Avail Use% Mounted on
/dev/mapper/fedora_greeneggs-root   50G   21G   27G  44% /
devtmpfs                           3.8G     0  3.8G   0% /dev
tmpfs                              3.8G   14M  3.8G   1% /dev/shm
tmpfs                              3.8G  984K  3.8G   1% /run
tmpfs                              3.8G     0  3.8G   0% /sys/fs/cgroup
tmpfs                              3.8G  3.4M  3.8G   1% /tmp
/dev/sda1                          477M   99M  349M  23% /boot
/dev/mapper/fedora_greeneggs-home  402G  184G  198G  49% /home

Để tìm thiết bị nào mà một tệp / thư mục cụ thể được tìm thấy trên đó, hãy cung cấp tệp đó làm đối số df. Sử dụng ví dụ của bạn:

$ df -h /mnt
Filesystem                         Size  Used Avail Use% Mounted on
/dev/sda1                          477M   99M  349M  23% /

Bạn cũng có thể sử dụng mountlệnh:

$ mount | grep '^/dev'
/dev/mapper/fedora_greeneggs-root on / type ext4 (rw,relatime,seclabel,data=ordered)
/dev/sda1 on /boot type ext4 (rw,relatime,seclabel,data=ordered)
/dev/mapper/fedora_greeneggs-home on /home type ext4 (rw,relatime,seclabel,data=ordered)

Thư mục được gắn cho mỗi thiết bị là đối số thứ 3 trong đầu ra ở trên. Vì vậy, đối với thiết bị /dev/sda1sẽ được /boot. Các thiết bị khác đang sử dụng LVM (Quản lý khối tin hợp lý) và sẽ cần được truy vấn thêm để biết thiết bị thực tế nào đang được LVM sử dụng.


Nếu $PWD(đó là những gì tôi đang gắn kết) bị chôn vùi trong một loạt các liên kết tượng trưng, ​​gắn kết liên kết, v.v. thì tôi sẽ cần kiểm tra đệ quy đường dẫn cho các điểm gắn kết.
StrongBad

Với các liên kết gắn kết mặc dù những gì hiển thị trong /proc/mounts"thứ" được gắn kết, ít nhất là trong suy nghĩ của tôi, không phải là thiết bị mà nó là thư mục / tập tin.
StrongBad

@StrongBad - readlink -f /mntchương trình gì?
slm

2
@StrongBad nếu bạn phải đối phó với việc xác định điểm gắn kết / thiết bị khi bị che khuất bởi các liên kết tượng trưng, ​​bạn nên đặt câu hỏi đó vào câu hỏi của mình. Nó sẽ làm cho nó dễ dàng hơn nhiều để có được câu trả lời đúng.
Patrick

readlink -f /mntcho/mnt
StrongBad

29

Trên Linux, chúng tôi đã findmnttừ util-linuxchính xác làm cho điều này

findmnt -n -o SOURCE --target /path/to/FILE

Ưu điểm của các giải pháp khác là nó vẫn hoạt động nếu các đường dẫn bị che khuất bởi các liên kết tượng trưng hoặc các liên kết gắn kết trùng lặp.


Điều này không làm việc cho tôi. Nó cho thấy nguồn của mọi mount trên hệ thống. findmnt từ produc-linux 2.23.2
bwduncan

@bwduncan đối với tôi nó hoạt động với 2.23.2. Có lẽ là một lỗi? Bạn có thể thử phiên bản mới nhất 2.29.2 không?
rudimeier

2.29 trên Ubuntu thực hiện thủ thuật. Không phải là một lỗi như vậy, thêm một tính năng :)
bwduncan

1
Cảm ơn! Đó chính xác là những gì tôi cần cho một kịch bản hệ thống.
vog

11

Phương pháp chính xác nhất mà tôi biết là sử dụng đầu ra của lệnh gọi hệ thống lstat (). Cụ thể, trường st_dev. Có một tiện ích dòng lệnh, stat (1) có thể được sử dụng để xem thông tin này. Ví dụ: đầu ra của "stat / etc / vấn đề" trên máy tính xách tay của tôi:

File: ‘/etc/issue’
  Size: 65          Blocks: 8          IO Block: 4096   regular file
Device: 801h/2049d  Inode: 1610916043  Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)

Lưu ý dòng thứ ba, trường đầu tiên, "Thiết bị". Ở đây nó liệt kê 801h. Giá trị đó có thể được tách thành hai byte, 8 và 1. byte đầu tiên được gọi là số chính, byte thứ hai là số phụ. Vì vậy, bước tiếp theo là tìm ra thiết bị chính 8, phụ 1 là gì.

Tôi thấy tư vấn / Proc / phân vùng là nhanh nhất. Trong trường hợp của tôi, / Proc / phân vùng có nội dung:

major minor  #blocks  name

   8       16  234431064 sdb
   8       17   33554432 sdb1
   8       18  200875608 sdb2
   8        0  500107608 sda
   8        1  500106584 sda1

Rõ ràng từ đầu ra chính 8, phụ 1 là sda1. Chúng tôi có thể xác nhận điều này với một ls -l / dev / sda1

brw-rw---- 1 root disk 8, 1 May  8 05:33 /dev/sda1

Lưu ý 8, 1 trước dấu thời gian.

Điều quan trọng là phải hiểu / nhớ rằng tên của tệp thiết bị như / dev / sda1 chỉ là nhãn. Các số chính và số phụ là các giá trị quan trọng, quan trọng của tệp thiết bị. Nếu bạn thấy tò mò, hãy kiểm tra tiện ích mknod (1) được sử dụng để tạo tập tin thiết bị. Tôi có thể tạo một mục mới / dev được gọi là aardvark với chính 8, phụ 18 với cú pháp sau:

mknod /dev/aardvark b 8 18

Sau đó, tôi có thể dễ dàng gắn kết nó:

mount /dev/aardvark /mnt

và, nếu chúng ta nhìn vào đầu ra của lệnh mount hoặc nội dung của / Proc / mounts và chúng ta thấy:

/dev/aardvark on /mnt type xfs (rw,relatime,attr2,inode64,noquota)

df -h cho thấy:

/dev/aardvark   192G  154G   38G  81% /mnt

... Dù sao đi nữa, quan điểm của tất cả những điều này là để minh họa rằng các chi tiết quan trọng để xác định một thiết bị khối là số chính và số phụ - không phải nhãn tệp thiết bị - và sử dụng lệnh gọi hệ thống lstat () là cách tốt nhất để truy vấn các giá trị đó.

Như một bình luận cuối cùng, tôi chỉ đọc lại câu hỏi của bạn để đảm bảo rằng tôi đã trả lời nó và tôi nhận ra rằng bạn đang hỏi nhãn thiết bị nguồn nào sẽ hiển thị trong / Proc / mounts cho một mount mount. Đó sẽ là nhãn thiết bị nguồn giống như đã được sử dụng trong lệnh gọi gốc (2) cho nguồn gắn kết hệ thống tập tin cho gắn kết liên kết. Có lẽ một ví dụ sẽ giúp:

Tôi có / dev / sdb2 và / dev / aardvark (giống như trên). Cả hai đều là chính 8, nhỏ 18. Lưu ý, tôi sẽ gắn cùng một hệ thống tập tin hai lần. Tôi làm như sau:

mkdir /mnt1 /mnt2 /foo

mount /dev/aardvark /mnt1
mount /dev/sdb2 /mnt2

Lưu ý rằng tôi tạo thư mục somedir trong / mnt1. Nhưng vì / mnt1 và / mnt2 có cùng hệ thống tập tin được gắn kết, somedir cũng sẽ có thể truy cập thông qua / mnt2.

mkdir /mnt1/somedir

mkdir /foo/left /foo/right

mount -o bind /mnt1/somedir /foo/left
mount -o bind /mnt2/somedir /foo/right

Bây giờ, nếu chúng ta kiểm tra / Proc / mounts, chúng ta sẽ thấy:

/dev/aardvark /mnt1 xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdb2 /mnt2 xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/aardvark /foo/left xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdb2 /foo/right xfs rw,relatime,attr2,inode64,noquota 0 0

Nhãn thiết bị nguồn trên các liên kết gắn kết / foo / ... giống như giá trị ban đầu được cung cấp trong lệnh gọi hệ thống tập tin (2). Hãy nhớ rằng, / dev / aardvark và / dev / sdb2 trong ví dụ của tôi là cùng một thiết bị.

Tôi nhận ra rằng tôi vừa gõ một cuốn tiểu thuyết và nửa đầu không thực sự trả lời câu hỏi của bạn, nhưng dường như thật lãng phí khi xóa nó. Có lẽ nó sẽ giúp người khác.

Chúc may mắn.

PS Hãy nhớ rằng một số hệ thống tệp dựa trên mạng - như NFS hoặc CIFS - hoặc là ảo - như Procfs hoặc sysfs và không có thiết bị chặn nguồn. Tôi không biết những gì sẽ được trả lại là thiết bị trong đầu ra stat, chỉ với những gì nó có giá trị.


1
Phần đầu tiên chắc chắn giúp tôi hiểu phần cuối.
StrongBad

Câu trả lời này không hoạt động cho các đường dẫn tmpfs. Bạn sẽ không tìm thấy st_dev nhỏ, chính trên / Proc / phân vùng.
mbello

@mbello Như tôi đã đề cập ở cuối câu trả lời của mình, phương pháp này sẽ không và không thể hoạt động đối với các hệ thống tệp không có thiết bị sao lưu - như gắn kết tmpfs.
etherfish

2

Cho các điểm gắn kết điển hình sau:

$ df --output=target
Mounted on
/
/dev
/run
/sys/fs/cgroup
/run/lock
/run/shm
/run/user

stat --format %m <path> sẽ chỉ in điểm gắn kết theo kiểu có thể theo dõi tròn (mặc dù bạn cần kiểm tra mã thoát để phát hiện rõ ràng lỗi cấp phép; phương pháp tiếp cận bảng gắn kết giành chiến thắng tại đây):

$ stat --format %m /
/
$ stat --format %m /tmp
/
$ stat --format %m /proc
/proc
$ stat --format %m /run
/run
$ stat --format %m /run/mount
/run
$ stat --format %m /run/user
/run/user
$ stat --format %m /run/user/1000/dconf
/run/user
$ stat --format %m /run/user/1000/gvfs
/run/user/1000/gvfs

Symlinks chăm sóc một chút như bình thường:

$ ls -lh ~/.gvfs
/home/cwillu/.gvfs -> /run/user/1000/gvfs
$ stat --format %m ~/.gvfs
/run/user/1000/gvfs
$ stat --format %m ~/.gvfs
/

Và tất nhiên hãy nhớ sử dụng dấu ngoặc kép khi viết kịch bản. Xem xét một đường dẫn điểm với không gian và như vậy:

$ mkdir /tmp/Something\ Like\ This\!
$ sudo mount none /tmp/Something\ Like\ This\! -t tmpfs
$ stat --format %m /tmp/Something\ Like\ This\!
/tmp/Something Like This!
$ touch /tmp/Something\ Like\ This\!/pretend-I\'m-big
$ ls /tmp/Something\ Like\ This\!
pretend-I'm-big

Lớn như thế nào bạn?

$ du $(stat --format %m /tmp/Something\ Like\ This\!/)
du: cannot access /tmp/Something: No such file or directory
du: cannot access Like: No such file or directory
du: cannot access This!: No such file or directory

$ du "$(stat --format %m /tmp/Something\ Like\ This\!/)"
0   /tmp/Something Like This!

Hoàn thành tab phân phối của tôi thậm chí không có quyền này, vì vậy chúng tôi sẽ chỉ ký tự đại diện cho điểm gắn kết ví dụ này với lợi nhuận vận chuyển và nguồn cấp dữ liệu và chạy không gian:

$ stat --format %m /tmp/Something*
/tmp/Something   
Like   This!

$ a="$(stat --format %m /tmp/Something*)"
    # the above assignment is actually the one place you don't need quotes, 
    # but `export a=...` or similar _would_ need them, so we'll just put them in;
    # they don't change the behaviour in this form of assignment.

$ stat "$a"
  File: ‘/tmp/Something   \r\n\rLike   This!’
  Size: 40          Blocks: 0          IO Block: 4096   directory
Device: 7bh/123d    Inode: 1279171     Links: 2
Access: (1777/drwxrwxrwt)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-09-30 11:43:17.933467344 -0600
Modify: 2016-09-30 11:43:17.933467344 -0600
Change: 2016-09-30 11:43:17.933467344 -0600
 Birth: -

1
Đánh dấu <kbd> được sử dụng cho một khóa, thay vì toàn bộ lệnh. Theo quan điểm khiêm tốn của tôi, nó không có vẻ tốt hơn.
Tomasz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.