web-dev-qa-db-fra.com

Déterminer sur quel périphérique se trouve un répertoire

Si je fais

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

l'entrée dans /proc/mounts est

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

qui est le périphérique monté sur /home et n'est pas facilement déductible de $PWD lequel est /test. Comment puis-je déterminer quel périphérique (c'est-à-dire/dev/sda2) va apparaître dans /proc/mounts en général étant donné que le montage de liaison peut être dans un répertoire/fichier potentiellement "masqué" par des liens symboliques, d'autres montages de liaison, etc.?

53
StrongBad

Si je comprends votre question, vous voulez savoir quel appareil a été utilisé pour un montage donné. Pour cela, vous pouvez utiliser la commande df:

$ 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

Pour trouver sur quel périphérique se trouve un fichier/répertoire particulier, donnez le fichier comme argument à df. En utilisant votre exemple:

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

Vous pouvez également utiliser la commande mount:

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

Le répertoire monté pour chaque périphérique est le troisième argument de la sortie ci-dessus. Donc, pour l'appareil /dev/sda1 serait /boot. Les autres appareils utilisent LVM (Logical Volume Management) et devraient être interrogés davantage pour savoir quel appareil réel est utilisé par LVM.

54
slm

Sous Linux, nous avons findmnt de util-linux exactement fait pour ça

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

L'avantage des autres solutions est qu'il fonctionne toujours si les chemins sont masqués par des liens symboliques ou des montages de liaison en double.

35
rudimeier

La méthode la plus précise que je connaisse consiste à utiliser la sortie de l'appel système lstat (). Plus précisément, le champ st_dev. Il existe un utilitaire de ligne de commande, stat (1) qui peut être utilisé pour afficher ces informations. Par exemple, la sortie de "stat/etc/issue" sur mon ordinateur portable:

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)

Remarquez la troisième ligne, le premier champ, "Device". Ici, il répertorie 801h. Cette valeur peut être séparée en deux octets, 8 et 1. Le premier octet est connu comme le nombre majeur, le deuxième octet est le nombre mineur. La prochaine étape consiste donc à déterminer quel est le périphérique majeur 8, mineur 1.

Je trouve que la consultation/proc/partitions est la plus rapide. Dans mon cas,/proc/partitions a le contenu:

major minor  #blocks  name

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

Il ressort assez clairement de cette sortie que le majeur 8, le mineur 1 est sda1. Nous pouvons le confirmer avec un ls -l/dev/sda1

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

Remarquez le 8, 1 avant l'horodatage.

Il est important de comprendre/de se rappeler que le nom d'un fichier de périphérique comme/dev/sda1 n'est qu'une étiquette. Les nombres majeurs et mineurs sont les valeurs importantes et importantes du fichier de périphérique. Si vous êtes curieux, consultez l'utilitaire mknod (1) utilisé pour créer des fichiers de périphérique. Je pourrais créer une nouvelle entrée/dev appelée aardvark avec le majeur 8, le mineur 18 avec la syntaxe suivante:

mknod /dev/aardvark b 8 18

Ensuite, je pourrais facilement le monter:

mount /dev/aardvark /mnt

et, si nous regardons la sortie de la commande mount ou le contenu de/proc/mounts et nous voyons:

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

df -h affiche:

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

... Quoi qu'il en soit, le but de tout cela est d'illustrer que les détails importants pour identifier un périphérique de bloc sont les nombres majeurs et mineurs - pas l'étiquette du fichier de périphérique - et que l'utilisation de l'appel système lstat () est la meilleure façon de interroger ces valeurs.

En dernier commentaire, je viens de relire votre question pour m'assurer que j'y répondais et je me suis rendu compte que vous demandiez quelle étiquette de périphérique source apparaîtrait dans/proc/mounts pour un montage de liaison. Ce serait la même étiquette de périphérique source que celle utilisée dans l'appel de montage (2) d'origine pour la source de point de montage du système de fichiers pour le montage de liaison. Peut-être qu'un exemple aiderait:

J'ai/dev/sdb2 et/dev/aardvark (les mêmes que ci-dessus). Ils sont tous deux majeurs 8, mineurs 18. Remarque, je vais monter le même système de fichiers deux fois. Je fais ce qui suit:

mkdir /mnt1 /mnt2 /foo

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

Notez que je crée le répertoire somedir dans/mnt1. Mais comme/mnt1 et/mnt2 ont le même système de fichiers monté, somedir sera également accessible via/mnt2.

mkdir /mnt1/somedir

mkdir /foo/left /foo/right

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

Maintenant, si nous vérifions/proc/mounts, nous voyons:

/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'étiquette du périphérique source sur les montages de liaison/foo/... est la même que la valeur fournie à l'origine dans l'appel du système de fichiers mount (2). N'oubliez pas que/dev/aardvark et/dev/sdb2 dans mon exemple sont le même périphérique.

Je me rends compte que je viens de taper un roman et que la première moitié ne répond pas vraiment à votre question, mais cela semblait être un gaspillage de le supprimer. Cela aidera peut-être quelqu'un d'autre.

Bonne chance.

P.S. Gardez à l'esprit que certains systèmes de fichiers sont basés sur le réseau - comme NFS ou CIFS - ou sont virtuels - comme procfs ou sysfs et n'ont pas de périphérique de bloc source. Je ne sais pas ce qui sera retourné comme périphérique dans la sortie stat, juste pour ce que ça vaut.

13
etherfish

Étant donné les points de montage typiques suivants:

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

stat --format %m <path> n'imprimera que les points de montage de manière circulaire (bien que vous deviez vérifier le code de sortie pour détecter sans ambiguïté une erreur d'autorisation; les approches de table de montage gagnent ici):

$ 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

Les liens symboliques prennent un peu de soin comme d'habitude:

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

Et bien sûr, n'oubliez pas d'utiliser des guillemets lors de l'écriture de scripts. Considérez un chemin de point de montage avec des espaces et autres:

$ 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

Quelle taille êtes-vous vous?

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

L'achèvement de l'onglet de ma distribution ne comprend même pas cela, nous allons donc simplement utiliser cet exemple de point de montage avec des retours chariot et des sauts de ligne et des espaces:

$ 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: -
2
Carey Underwood