Tentukan di mana perangkat direktori berada

50

Jika aku melakukan

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

entri /proc/mountsadalah

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

yang merupakan perangkat yang dipasang ke /homedan tidak mudah dikurangkan dari $PWDmana /test. Bagaimana saya bisa menentukan perangkat mana (yaitu, / dev / sda2) akan muncul secara /proc/mountsumum mengingat bind mount mungkin ke direktori / file yang berpotensi "dikaburkan" oleh symlink, bind mount lainnya, dll?

StrongBad
sumber

Jawaban:

49

Jika saya mengerti pertanyaan Anda, Anda ingin tahu perangkat mana yang digunakan untuk pemasangan yang diberikan. Untuk ini, Anda dapat menggunakan dfperintah:

$ 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

Untuk menemukan di mana perangkat file / direktori tertentu ditemukan, berikan file sebagai argumen df. Menggunakan contoh Anda:

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

Anda juga dapat menggunakan mountperintah:

$ 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)

Direktori yang dipasang untuk setiap perangkat adalah argumen ke-3 dalam output di atas. Jadi untuk perangkat /dev/sda1akan /boot. Perangkat lain memanfaatkan LVM (Logical Volume Management) dan perlu ditanyakan lebih lanjut untuk mengetahui perangkat mana yang sebenarnya digunakan oleh LVM.

slm
sumber
Jika $PWD(yang saya mount) dimakamkan di serangkaian symlink, bind mounts, dll maka saya akan perlu memeriksa secara rekursif jalur untuk titik mount.
StrongBad
Dengan bind mounts meskipun apa yang muncul di /proc/mounts"benda" yang dipasang, setidaknya dalam pikiran saya, bukan perangkat itu adalah direktori / file.
StrongBad
@ StrongBad - apa yang readlink -f /mntditampilkan?
slm
2
@ StrongBad jika Anda harus berurusan dengan menentukan titik pemasangan / perangkat ketika dikaburkan oleh symlink, Anda harus memasukkannya ke dalam pertanyaan Anda. Ini akan membuatnya lebih mudah untuk mendapatkan jawaban yang benar.
Patrick
readlink -f /mntmemberi/mnt
StrongBad
30

Di Linux kami membuat findmntdari yang util-linuxtepat untuk ini

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

Keuntungan tentang solusi lain adalah masih berfungsi jika jalur dikaburkan oleh symlink atau duplikat bind mounts.

rudimeier
sumber
Ini tidak berhasil untuk saya. Ini menunjukkan sumber dari setiap mount pada sistem. findmnt dari util-linux 2.23.2
bwduncan
@ bwduncan bagi saya ini berfungsi dengan 2.23.2. Mungkin bug? Bisakah Anda mencoba versi terbaru 2.29.2?
rudimeier
2.29 di Ubuntu melakukan trik. Bukan bug seperti itu, lebih banyak fitur :)
bwduncan
1
Terima kasih! Itulah tepatnya yang saya butuhkan untuk skrip sistem.
vog
12

Metode paling akurat yang saya tahu adalah menggunakan output dari panggilan sistem lstat (). Secara khusus, bidang st_dev. Ada utilitas baris perintah, stat (1) yang dapat digunakan untuk melihat informasi ini. Misalnya, keluaran "stat / etc / issue" di laptop saya:

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)

Perhatikan baris ketiga, bidang pertama, "Perangkat". Ini daftar 801j. Nilai itu dapat dipisahkan menjadi dua byte, 8 dan 1. Byte pertama dikenal sebagai angka utama, byte kedua adalah angka minor. Jadi, langkah selanjutnya adalah mencari tahu apa perangkat utama 8, minor 1 itu.

Saya menemukan konsultasi / proc / partisi menjadi yang tercepat. Dalam kasus saya, / proc / partisi memiliki konten:

major minor  #blocks  name

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

Dari keluaran itu agak jelas bahwa mayor 8, minor 1 adalah sda1. Kami dapat mengkonfirmasi ini dengan ls -l / dev / sda1

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

Perhatikan 8, 1 sebelum datestamp.

Sangat penting untuk memahami / mengingat bahwa nama file perangkat seperti / dev / sda1 hanya label. Angka utama dan kecil adalah nilai penting dan penting dari file perangkat. Jika Anda ingin tahu, periksa utilitas mknod (1) yang digunakan untuk membuat file perangkat. Saya dapat membuat entri baru / dev yang disebut aardvark dengan major 8, minor 18 dengan sintaks berikut:

mknod /dev/aardvark b 8 18

Lalu, saya bisa dengan mudah memasangnya:

mount /dev/aardvark /mnt

dan, jika kita melihat output dari perintah mount atau isi / proc / mounts dan kita melihat:

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

df -h menunjukkan:

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

... Bagaimanapun, inti dari semua ini adalah untuk menggambarkan bahwa detail penting untuk mengidentifikasi perangkat blok adalah angka utama dan kecil - bukan label file perangkat - dan bahwa menggunakan system call lstat () adalah cara terbaik untuk menanyakan nilai-nilai itu.

Sebagai komentar terakhir, saya hanya membaca ulang pertanyaan Anda untuk memastikan saya menjawabnya dan saya menyadari Anda menanyakan label perangkat sumber apa yang akan muncul di / proc / mounts untuk bind mount. Itu akan menjadi label perangkat sumber yang sama seperti yang digunakan dalam panggilan mount asli (2) untuk sumber mountpoint filesystem untuk bind mount. Mungkin sebuah contoh akan membantu:

Saya memiliki / dev / sdb2 dan / dev / aardvark (sama seperti di atas). Keduanya 8 besar, minor 18. Catatan, saya akan memasang sistem file yang sama dua kali. Saya melakukan hal berikut:

mkdir /mnt1 /mnt2 /foo

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

Perhatikan bahwa saya membuat direktori somedir di / mnt1. Tetapi karena / mnt1 dan / mnt2 memiliki sistem file yang sama, somedir juga dapat dijangkau melalui / mnt2.

mkdir /mnt1/somedir

mkdir /foo/left /foo/right

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

Sekarang, jika kita memeriksa / proc / mounts, kita melihat:

/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

Label perangkat sumber pada bind mount / foo / ... sama dengan nilai yang semula disediakan dalam panggilan mount filesystem (2). Ingat, / dev / aardvark dan / dev / sdb2 dalam contoh saya adalah perangkat yang sama.

Saya sadar saya baru saja mengetik novel dan babak pertama tidak benar-benar menjawab pertanyaan Anda sama sekali, tetapi sepertinya sia-sia menghapusnya. Mungkin itu akan membantu orang lain.

Semoga berhasil.

PS Perlu diingat bahwa beberapa sistem file berbasis jaringan - seperti NFS atau CIFS - atau virtual - seperti procfs atau sysfs dan tidak memiliki perangkat blok sumber. Saya tidak tahu apa yang akan dikembalikan sebagai perangkat dalam output stat, hanya untuk apa nilainya.

etherfish
sumber
1
Bagian pertama pasti membantu saya memahami bagian terakhir.
StrongBad
Jawaban ini tidak berfungsi untuk jalur tmpfs. Anda tidak akan menemukan st_dev minor, mayor pada / proc / partisi.
mbello
@ mbello Seperti yang saya sebutkan di akhir jawaban saya, metode ini tidak akan dan tidak dapat bekerja untuk sistem file yang tidak memiliki perangkat pendukung - seperti tmpfs mount.
etherfish
2

Diberi mountpoints khas berikut:

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

stat --format %m <path> hanya akan mencetak mountpoint secara bulat (meskipun Anda perlu memeriksa kode keluar untuk secara jelas mendeteksi kesalahan izin; pendekatan mount-table menang di sini):

$ 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

Symlink berhati-hati seperti biasa:

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

Dan tentu saja ingatlah untuk menggunakan kutipan saat membuat skrip. Pertimbangkan jalur mountpoint dengan spasi dan semacamnya:

$ 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

Seberapa besar adalah Anda?

$ 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!

Penyelesaian tab distro saya bahkan tidak dapat memperbaiki ini, jadi kami hanya akan menambahkan contoh mountpoint ini dengan carriage return dan linefeed dan menjalankan spasi:

$ 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: -
Carey Underwood
sumber
1
Markup <kbd> digunakan untuk satu kunci, bukan seluruh perintah. Tidak terlihat lebih baik seperti ini, menurut pendapat saya.
Tomasz