Determina su quale dispositivo si trova una directory


50

Se lo faccio

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

l'ingresso /proc/mountsè

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

quale è il dispositivo su cui è montato /homee non è facilmente deducibile da $PWDquale è /test. Come posso determinare quale dispositivo (cioè, / dev / sda2) verrà mostrato /proc/mountsin generale, dato che il mount del bind può essere su una directory / file che è potenzialmente "oscurato" da link simbolici, altri mount di bind, ecc.?

Risposte:


49

Se capisco la tua domanda, vuoi sapere quale dispositivo è stato utilizzato per un determinato supporto. Per questo è possibile utilizzare il dfcomando:

$ 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

Per trovare su quale dispositivo si trova un determinato file / directory, fornire il file come argomento df. Usando il tuo esempio:

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

Puoi anche usare il mountcomando:

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

La directory montata per ciascun dispositivo è il terzo argomento nell'output sopra. Quindi per il dispositivo /dev/sda1sarebbe /boot. Gli altri dispositivi utilizzano LVM (Logical Volume Management) e dovrebbero essere sottoposti a ulteriori interrogazioni per sapere quale dispositivo reale viene utilizzato da LVM.


Se $PWD(che è quello che sto montando) è sepolto in una serie di collegamenti simbolici, attacchi di associazione, ecc., Allora avrei bisogno di esaminare ricorsivamente il percorso per i punti di montaggio.
StrongBad

Con i bind mount, nonostante ciò che appare nella /proc/mounts"cosa" che è montata, almeno nella mia mente, non è il dispositivo, è la directory / file.
StrongBad

@StrongBad: cosa readlink -f /mntmostra?
slm

2
@StrongBad se hai a che fare con la determinazione del punto di montaggio / dispositivo quando oscurato da symlink, dovresti metterlo nella tua domanda. Sarà molto più facile ottenere la risposta giusta.
Patrick,

readlink -f /mnt/mnt
StrongBad

30

Su Linux abbiamo findmntda util-linuxesattamente fatto per questo

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

Il vantaggio rispetto ad altre soluzioni è che funziona ancora se i percorsi sono oscurati da collegamenti simbolici o attacchi bind duplicati.


Questo non funziona per me. Mostra la fonte di ogni mount sul sistema. findmnt da util-linux 2.23.2
bwduncan,

@bwduncan per me funziona con 2.23.2. Forse un insetto? Potresti provare l'ultima versione 2.29.2?
rudimeier,

2.29 su Ubuntu fa il trucco. Non un bug in quanto tale, più una caratteristica :)
bwduncan,

1
Grazie! Questo è esattamente ciò di cui avevo bisogno per uno script di sistema.
vog

12

Il metodo più accurato di cui sono a conoscenza è utilizzare l'output della chiamata di sistema lstat (). In particolare, il campo st_dev. C'è un'utilità della riga di comando, stat (1) che può essere utilizzata per visualizzare queste informazioni. Ad esempio, l'output di "stat / etc / issue" sul mio 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)

Si noti la terza riga, primo campo, "Dispositivo". Qui elenca 801h. Tale valore può essere separato in due byte, 8 e 1. Il primo byte è noto come il numero maggiore, il secondo byte è il numero minore. Quindi, il prossimo passo è capire quale dispositivo maggiore 8, minore 1.

Trovo che la consulenza / proc / partizioni sia la più veloce. Nel mio caso, / proc / partitions ha il contenuto:

major minor  #blocks  name

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

È piuttosto chiaro da quell'output che il maggiore 8, il minore 1 è sda1. Possiamo confermarlo con ls -l / dev / sda1

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

Notare l'8, 1 prima del datestamp.

È importante capire / ricordare che il nome di un file del dispositivo come / dev / sda1 è solo un'etichetta. I numeri maggiori e minori sono i valori significativi e importanti del file del dispositivo. Se sei curioso, controlla l'utilità mknod (1) utilizzata per creare i file del dispositivo. Potrei creare una nuova voce / dev chiamata aardvark con major 8, minor 18 con la seguente sintassi:

mknod /dev/aardvark b 8 18

Quindi, potrei facilmente montarlo:

mount /dev/aardvark /mnt

e, se guardiamo all'output del comando mount o al contenuto di / proc / mounts e vediamo:

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

df -h mostra:

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

... Ad ogni modo, il punto di tutto ciò è illustrare che i dettagli importanti per l'identificazione di un dispositivo a blocchi sono i numeri maggiori e minori - non l'etichetta del file del dispositivo - e che l'uso della chiamata di sistema lstat () è il modo migliore per interrogare quei valori.

Come ultimo commento, ho appena riletto la tua domanda per assicurarmi di rispondere e mi sono reso conto che stavi chiedendo quale etichetta del dispositivo sorgente sarebbe stata mostrata in / proc / mounts per un mount bind. Sarebbe la stessa etichetta del dispositivo sorgente utilizzata nella chiamata mount originale (2) per l'origine mountpoint del filesystem per il mount bind. Forse un esempio potrebbe aiutare:

Ho / dev / sdb2 e / dev / aardvark (lo stesso di cui sopra). Sono entrambi maggiori 8, minori 18. Nota, monterò due volte lo stesso filesystem. Faccio quanto segue:

mkdir /mnt1 /mnt2 /foo

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

Nota che creo la directory somedir in / mnt1. Ma poiché / mnt1 e / mnt2 hanno lo stesso filesystem montato, anche somedir sarà raggiungibile tramite / mnt2.

mkdir /mnt1/somedir

mkdir /foo/left /foo/right

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

Ora, se controlliamo / proc / mounts, vediamo:

/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

L'etichetta del dispositivo di origine sui mount bind / foo / ... è uguale al valore originariamente fornito nella chiamata mount (2) del filesystem. Ricorda, / dev / aardvark e / dev / sdb2 nel mio esempio sono lo stesso dispositivo.

Mi rendo conto di aver appena scritto un romanzo e la prima metà non risponde affatto alla tua domanda, ma mi è sembrato un tale spreco eliminarlo. Forse aiuterà qualcun altro.

In bocca al lupo.

PS Tieni presente che alcuni filesystem sono basati su rete - come NFS o CIFS - o sono virtuali - come procfs o sysfs e non hanno un dispositivo a blocchi sorgente. Non so cosa verrà restituito come dispositivo nell'output delle statistiche, solo per quello che vale.


1
La prima parte mi aiuta sicuramente a capire l'ultima parte.
StrongBad

Questa risposta non funziona per i percorsi tmpfs. Non troverai lo st_dev minor, major su / proc / partitions.
mbello,

@mbello Come menziono alla fine della mia risposta, questo metodo non funzionerà e non potrà funzionare con filesystem che non dispongono di un dispositivo di supporto, come i montaggi tmpfs.
etherfish

2

Dati i seguenti mountpoint tipici:

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

stat --format %m <path> stamperà solo mountpoint in modo round-trappable (anche se è necessario controllare il codice di uscita per rilevare in modo inequivocabile un errore di autorizzazione; gli approcci della tabella di mount vincono qui):

$ 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

I link simbolici prendono un po 'di attenzione come al solito:

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

E ovviamente ricordati di usare le virgolette durante lo scripting. Considera un percorso mountpoint con spazi e simili:

$ 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

Quanto sei grande ?

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

Il completamento della scheda della mia distro non riesce nemmeno a farlo bene, quindi utilizzeremo solo jolly questo mountpoint di esempio con ritorni a capo, avanzamenti di riga e corse di spazi:

$ 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
Il markup <kbd> viene utilizzato per una singola chiave, anziché per un intero comando. A mio avviso, non sembra migliore in questo modo.
Tomasz,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.