Określ, na jakim urządzeniu znajduje się katalog


49

Jeśli zrobię

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

wpis /proc/mountsjest

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

którym jest urządzenie, które jest zamontowane /homei od $PWDktórego nie można łatwo wydedukować /test. Jak mogę ustalić, które urządzenie (tj. / Dev / sda2) ma się /proc/mountsogólnie wyświetlać, biorąc pod uwagę, że podłączenie może być do katalogu / pliku, który jest potencjalnie „zasłonięty” przez dowiązania symboliczne, inne podłączenia itp.?

Odpowiedzi:


49

Jeśli rozumiem twoje pytanie, chcesz wiedzieć, które urządzenie zostało użyte dla danego montażu. W tym celu możesz użyć dfpolecenia:

$ 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

Aby znaleźć urządzenie, na którym znajduje się określony plik / katalog, podaj plik jako argument df. Na twoim przykładzie:

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

Możesz także użyć mountpolecenia:

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

Katalog zamontowany dla każdego urządzenia jest trzecim argumentem w wynikach powyżej. Tak /dev/sda1byłoby w przypadku urządzenia /boot. Inne urządzenia korzystają z LVM (Logical Volume Management) i należy je zapytać, aby dowiedzieć się, które rzeczywiste urządzenie jest używane przez LVM.


Jeśli $PWD(to, co montuję) jest pochowany w szeregu dowiązań symbolicznych, powiązań montowań itp., Wtedy musiałbym rekurencyjnie sprawdzać ścieżkę pod kątem punktów montowania.
StrongBad

Z mocowaniami binda, pomimo tego, co pojawia się w /proc/mountszamontowanej „rzeczy”, przynajmniej moim zdaniem nie jest to urządzenie, ale katalog / plik.
StrongBad

@StrongBad - co readlink -f /mntpokazuje?
slm

2
@ StrongBad, jeśli masz do czynienia z określeniem punktu / urządzenia montowania, gdy są zasłonięte dowiązaniami symbolicznymi, powinieneś o to zapytać. Ułatwi to uzyskanie właściwej odpowiedzi.
Patrick

readlink -f /mntdaje/mnt
StrongBad

29

W Linuksie mamy findmntz util-linuxdokładnie w tej sprawie

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

Zaletą innych rozwiązań jest to, że nadal działa, jeśli ścieżki są zasłonięte przez dowiązania symboliczne lub duplikaty montowań powiązań.


To mi nie działa. Pokazuje źródło każdego montażu w systemie. findmnt z util-linux
2.23.2

@ bwduncan dla mnie działa z 2.23.2. Może błąd? Czy możesz wypróbować najnowszą wersję 2.29.2?
rudimeier

2.29 na Ubuntu załatwia sprawę. Nie taki błąd, więcej funkcji :)
bwduncan

1
Dzięki! Właśnie tego potrzebowałem do skryptu systemowego.
vog

11

Najdokładniejszą znaną mi metodą jest użycie wyniku wywołania systemowego lstat (). W szczególności pole st_dev. Istnieje narzędzie wiersza poleceń, stat (1), którego można użyć do wyświetlenia tych informacji. Na przykład dane wyjściowe „stat / etc / issue” na moim laptopie:

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)

Zwróć uwagę na trzeci wiersz, pierwsze pole „Device”. Oto lista 801 godzin. Wartość tę można podzielić na dwa bajty, 8 i 1. Pierwszy bajt jest znany jako liczba główna, drugi bajt jest liczbą podrzędną. Kolejnym krokiem jest ustalenie, jakie urządzenie ma numer 8, numer 1.

Uważam, że konsultacje / proc / partycje są najszybsze. W moim przypadku / proc / partitions ma zawartość:

major minor  #blocks  name

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

Z danych wyjściowych wynika raczej, że major 8, minor 1 to sda1. Możemy to potwierdzić za pomocą ls -l / dev / sda1

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

Zwróć uwagę na 8, 1 przed datestamp.

Ważne jest, aby zrozumieć / pamiętać, że nazwa pliku urządzenia, takiego jak / dev / sda1, jest tylko etykietą. Liczby główne i podrzędne są znaczącymi, ważnymi wartościami pliku urządzenia. Jeśli jesteś ciekawy, sprawdź narzędzie mknod (1) używane do tworzenia plików urządzeń. Mógłbym utworzyć nowy wpis / dev o nazwie aardvark z major 8, minor 18 z następującą składnią:

mknod /dev/aardvark b 8 18

Następnie mógłbym łatwo go zamontować:

mount /dev/aardvark /mnt

a jeśli spojrzymy na wynik polecenia mount lub zawartość / proc / mounts i zobaczymy:

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

df -h pokazuje:

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

... W każdym razie celem tego wszystkiego jest zilustrowanie, że ważnymi szczegółami do identyfikacji urządzenia blokowego są liczby główne i podrzędne - nie etykieta pliku urządzenia - i że użycie wywołania systemowego lstat () jest najlepszym sposobem na sprawdzaj te wartości.

Jako ostatni komentarz, po prostu ponownie przeczytałem twoje pytanie, aby upewnić się, że odpowiadam na nie, i zdałem sobie sprawę, że pytasz, jaka etykieta urządzenia źródłowego pojawi się w / proc / mounts dla podłączenia bind. Byłaby to ta sama etykieta urządzenia źródłowego, która została użyta w pierwotnym wywołaniu mount (2) dla źródła punktu montowania systemu plików dla podłączenia bind. Być może przykład pomoże:

Mam / dev / sdb2 i / dev / aardvark (to samo co powyżej). Obie mają główną 8, mniejszą 18. Uwaga, dwa razy podłączę ten sam system plików. Wykonuję następujące czynności:

mkdir /mnt1 /mnt2 /foo

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

Zauważ, że tworzę katalog somedir w / mnt1. Ponieważ jednak / mnt1 i / mnt2 mają ten sam system plików, somedir będzie również dostępny przez / mnt2.

mkdir /mnt1/somedir

mkdir /foo/left /foo/right

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

Teraz, jeśli sprawdzimy / proc / mounts, zobaczymy:

/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

Etykieta urządzenia źródłowego w mocowaniach powiązań / foo / ... jest taka sama, jak wartość pierwotnie podana w wywołaniu mount (2) systemu plików. Pamiętaj, że / dev / aardvark i / dev / sdb2 w moim przykładzie są tym samym urządzeniem.

Zdaję sobie sprawę, że właśnie napisałem książkę, a pierwsza połowa w ogóle nie odpowiada na twoje pytanie, ale usunięcie go było marnotrawstwem. Być może pomoże to komuś innemu.

Powodzenia.

PS Należy pamiętać, że niektóre systemy plików są oparte na sieci - jak NFS lub CIFS - lub wirtualne - jak procfs lub sysfs i nie mają źródłowego urządzenia blokującego. Nie wiem, co zostanie zwrócone jako urządzenie na wyjściu statystyki, tylko za to, co jest warte.


1
Pierwsza część zdecydowanie pomaga mi zrozumieć ostatnią część.
StrongBad

Ta odpowiedź nie działa dla ścieżek tmpfs. Nie znajdziesz st_dev minor, major na / proc / partitions.
mbello,

@mbello Jak już wspomniałem na końcu mojej odpowiedzi, ta metoda nie działa i nie może działać w systemach plików, które nie mają urządzenia do tworzenia kopii zapasowych - takich jak montowanie tmpfs.
Eterfish

2

Biorąc pod uwagę następujące typowe punkty montowania:

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

stat --format %m <path> wypisze tylko punkt montowania w sposób możliwy do zaokrąglenia (chociaż trzeba sprawdzić kod wyjścia, aby jednoznacznie wykryć błąd uprawnień; podejścia do tabeli montowania wygrywają tutaj):

$ 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 zachowują ostrożność jak zwykle:

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

I oczywiście pamiętaj, aby używać skryptów podczas pisania skryptów. Rozważ ścieżkę punktu montowania ze spacjami i takie:

$ 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

Jak duże ty?

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

Uzupełnianie tabulatorów mojej dystrybucji nawet tego nie robi poprawnie, więc po prostu zastosujemy ten przykładowy punkt montowania ze znakami powrotu karetki, znakami linii i ciągami spacji:

$ 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
Znacznik <kbd> jest używany dla pojedynczego klawisza, a nie dla całego polecenia. Moim skromnym zdaniem nie wygląda to lepiej w ten sposób.
Tomasz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.