Bestimmen Sie, auf welchem ​​Gerät sich ein Verzeichnis befindet

49

Wenn ich mache

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

der eintrag in /proc/mountsist

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

/homeWelches ist das Gerät, das montiert ist und von dem nicht leicht ableitbar $PWDist /test. Wie kann ich bestimmen, welches Gerät (dh / dev / sda2) /proc/mountsim Allgemeinen angezeigt wird, vorausgesetzt , das Bindungs-Mount befindet sich möglicherweise in einem Verzeichnis / einer Datei, das / die möglicherweise durch Symlinks, andere Bindungs-Mounts usw. "verdeckt" wird?

StrongBad
quelle

Antworten:

49

Wenn ich Ihre Frage verstehe, möchten Sie wissen, welches Gerät für ein bestimmtes Mount verwendet wurde. Hierzu können Sie den dfBefehl verwenden:

$ 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

Um herauszufinden, auf welchem ​​Gerät sich eine bestimmte Datei / ein bestimmtes Verzeichnis befindet, geben Sie die Datei als Argument an df. Verwenden Sie Ihr Beispiel:

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

Sie können auch den folgenden mountBefehl verwenden:

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

Das für jedes Gerät gemountete Verzeichnis ist das dritte Argument in der obigen Ausgabe. Also für Gerät /dev/sda1wäre /boot. Die anderen Geräte verwenden LVM (Logical Volume Management) und müssen weiter abgefragt werden, um zu wissen, welches tatsächliche Gerät von LVM verwendet wird.

slm
quelle
Wenn $PWD(das ist, was ich einhänge) in einer Reihe von Symlinks, Bindungs-Reittieren usw. begraben ist, müsste ich den Pfad rekursiv auf Einhängepunkte untersuchen.
StrongBad
Bei Bind-Mounts ist trotz allem, was in /proc/mountsdem "Ding" auftaucht , das gemountet wird, zumindest in meinem Kopf, nicht das Gerät, sondern das Verzeichnis / die Datei.
StrongBad
@StrongBad - was readlink -f /mntzeigt?
slm
2
@StrongBad Wenn Sie sich mit der Bestimmung des Mount-Punkts / Geräts befassen müssen, wenn es durch Symlinks verdeckt wird, sollten Sie dies in Ihre Frage stellen. Dadurch wird es viel einfacher, die richtige Antwort zu finden.
Patrick
readlink -f /mntgibt/mnt
StrongBad
29

Unter Linux haben wir findmntvon util-linuxgenau dafür gemacht

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

Der Vorteil gegenüber anderen Lösungen besteht darin, dass sie weiterhin funktionieren, wenn Pfade durch Symlinks oder doppelte Bindungsbereitstellungen verdeckt werden.

rudimeier
quelle
Das funktioniert bei mir nicht. Es zeigt die Quelle jedes Mount auf dem System. findmnt von util-linux 2.23.2
bwduncan
@bwduncan bei mir klappt es mit 2.23.2. Vielleicht ein Bug? Könnten Sie die neueste Version 2.29.2 ausprobieren?
Rudimeier
2.29 auf Ubuntu macht den Trick. Kein Fehler als solcher, eher ein Feature :)
bwduncan
1
Vielen Dank! Genau das brauchte ich für ein Systemskript.
Vog
11

Die genaueste Methode, die mir bekannt ist, ist die Verwendung der Ausgabe des Systemaufrufs lstat (). Insbesondere das Feld st_dev. Es gibt ein Befehlszeilendienstprogramm, stat (1), mit dem diese Informationen angezeigt werden können. Zum Beispiel die Ausgabe von "stat / etc / issue" auf meinem Laptop:

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)

Beachten Sie die dritte Zeile im ersten Feld "Gerät". Hier sind 801h aufgelistet. Dieser Wert kann in zwei Bytes (8 und 1) unterteilt werden. Das erste Byte ist als Hauptzahl bekannt, das zweite Byte als Nebenzahl. Der nächste Schritt ist also herauszufinden, welches Gerät Major 8, Moll 1 ist.

Ich finde Consulting / Proc / Partitions am schnellsten. In meinem Fall hat / proc / partitions den Inhalt:

major minor  #blocks  name

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

Aus dieser Ausgabe geht ziemlich klar hervor, dass Dur 8, Moll 1 sda1 ist. Wir können dies mit ls -l / dev / sda1 bestätigen

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

Beachten Sie die 8, 1 vor dem Datumsstempel.

Es ist wichtig zu verstehen, dass der Name einer Gerätedatei wie / dev / sda1 nur eine Bezeichnung ist. Die Haupt- und Nebenzahlen sind die signifikanten, wichtigen Werte der Gerätedatei. Wenn Sie neugierig werden, schauen Sie sich das Dienstprogramm mknod (1) an, mit dem Sie Gerätedateien erstellen. Ich könnte einen neuen / dev-Eintrag namens aardvark mit Dur 8, Moll 18 mit der folgenden Syntax erstellen:

mknod /dev/aardvark b 8 18

Dann könnte ich es leicht montieren:

mount /dev/aardvark /mnt

Und wenn wir uns die Ausgabe des Befehls mount oder den Inhalt von / proc / mounts ansehen und Folgendes sehen:

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

df -h zeigt:

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

... Auf jeden Fall geht es darum zu veranschaulichen, dass die wichtigsten Details zur Identifizierung eines Blockgeräts die Major- und Minor-Nummern sind - nicht die Bezeichnung der Gerätedatei - und dass die Verwendung des Systemaufrufs lstat () der beste Weg dazu ist Fragen Sie diese Werte ab.

Als letzten Kommentar habe ich Ihre Frage noch einmal gelesen, um sicherzugehen, dass ich sie beantwortet habe, und festgestellt, dass Sie gefragt haben, welche Bezeichnung für das Quellgerät in / proc / mounts für ein Bind-Mount angezeigt werden soll. Dies wäre die gleiche Bezeichnung für das Quellgerät, die im ursprünglichen Aufruf von mount (2) für die Dateisystem-Mountpoint-Quelle für den Bind-Mount verwendet wurde. Vielleicht würde ein Beispiel helfen:

Ich habe / dev / sdb2 und / dev / aardvark (das gleiche wie oben). Sie sind beide Dur 8, Moll 18. Beachten Sie, dass ich das gleiche Dateisystem zweimal mounten werde. Ich mache folgendes:

mkdir /mnt1 /mnt2 /foo

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

Beachten Sie, dass ich das Verzeichnis somedir in / mnt1 mache. Da für / mnt1 und / mnt2 dasselbe Dateisystem aktiviert ist, ist somedir auch über / mnt2 erreichbar.

mkdir /mnt1/somedir

mkdir /foo/left /foo/right

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

Wenn wir nun / proc / mounts überprüfen, sehen wir:

/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

Die Bezeichnung des Quellgeräts in den Bindungs-Mounts / foo / ... entspricht dem Wert, der ursprünglich im Dateisystem-Mount (2) -Aufruf angegeben wurde. Denken Sie daran, dass / dev / aardvark und / dev / sdb2 in meinem Beispiel dasselbe Gerät sind.

Mir ist klar, dass ich gerade einen Roman geschrieben habe und die erste Hälfte Ihre Frage nicht wirklich beantwortet hat, aber es schien mir eine Verschwendung, ihn zu löschen. Vielleicht hilft es jemand anderem.

Viel Glück.

PS Denken Sie daran, dass einige Dateisysteme netzwerkbasiert sind (z. B. NFS oder CIFS) oder virtuell (z. B. procfs oder sysfs) und über kein Quellblockgerät verfügen. Ich weiß nicht, was als Gerät in der Statistikausgabe zurückgegeben wird, nur für das, was es wert ist.

Ätherfisch
quelle
1
Der erste Teil hilft mir auf jeden Fall, den letzten Teil zu verstehen.
StrongBad
Diese Antwort funktioniert nicht für tmpfs-Pfade. Sie finden st_dev minor und major nicht in / proc / Partitionen.
mbello
@mbello Wie ich am Ende meiner Antwort erwähne, funktioniert diese Methode nicht und kann nicht für Dateisysteme verwendet werden, die kein Backup-Gerät haben - wie tmpfs-Mounts.
Ätherfisch
2

Angesichts der folgenden typischen Mountpunkte:

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

stat --format %m <path> Gibt nur den Einhängepunkt in runder Form aus (obwohl Sie den Exit-Code überprüfen müssen, um einen Berechtigungsfehler eindeutig zu erkennen; hier gewinnen die Einhängepunkt-Ansätze):

$ 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 sind wie gewohnt vorsichtig:

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

Und denken Sie natürlich daran, beim Schreiben von Skripten Anführungszeichen zu verwenden. Betrachten Sie einen Mountpoint-Pfad mit Leerzeichen und so weiter:

$ 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

Wie groß bist du

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

Die Tab-Vervollständigung meiner Distribution macht dies nicht einmal richtig. Deshalb werden wir diesen Beispiel-Mountpoint mit Zeilenumbrüchen, Zeilenvorschüben und Leerzeichenfolgen als Platzhalter verwenden:

$ 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
quelle
1
Das <kbd> -Markup wird für eine einzelne Taste anstelle eines ganzen Befehls verwendet. So sieht es meiner bescheidenen Meinung nach nicht besser aus.
Tomasz