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

51

Si je fais

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

l'entrée en /proc/mountsest

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

qui est le dispositif qui est monté sur /homeet ne sont pas facilement déduire de ce $PWDqui est /test. Comment puis-je déterminer quel périphérique (c'est-à-dire / dev / sda2) va apparaître /proc/mountsen 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.?

StrongBad
la source

Réponses:

49

Si je comprends votre question, vous voulez savoir quel périphérique a été utilisé pour un montage donné. Pour cela, vous pouvez utiliser la dfcommande:

$ 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 le périphérique sur lequel se trouve un fichier / répertoire particulier, donnez-le 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 mountcommande:

$ 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/sda1serait /boot. Les autres périphériques utilisent LVM (Logical Volume Management) et il faudrait demander plus avant pour savoir quel périphérique est actuellement utilisé par LVM.

slm
la source
Si $PWD(ce que je suis en train de monter) est enterré dans une série de liens symboliques, de montages de liaisons, etc., il me faudrait alors examiner de manière récursive le chemin des points de montage.
StrongBad
Avec les montages en liaison malgré ce qui apparaît dans /proc/mountsla "chose" qui est montée, du moins dans mon esprit, ce n’est pas le périphérique qui est le répertoire / fichier.
StrongBad
@StrongBad - que readlink -f /mntmontre-t-on?
slm
2
@StrongBad si vous devez déterminer le point de montage / le périphérique masqué par des liens symboliques, vous devriez l'indiquer dans votre question. Il sera beaucoup plus facile d'obtenir la bonne réponse.
Patrick
readlink -f /mntdonne/mnt
StrongBad
30

Sur Linux , nous avons findmntd' util-linuxexactement fait pour cette

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

L'avantage des autres solutions est que cela fonctionne toujours si les chemins sont obscurcis par des liens symboliques ou des montages de liaisons en double.

rudimeier
la source
Cela ne marche pas pour moi. Il montre la source de chaque montage sur le système. findmnt from util-linux 2.23.2
bwduncan
@bwduncan pour moi cela fonctionne avec 2.23.2. Peut-être un bug? Pourriez-vous essayer la dernière version 2.29.2?
Rudimeier
2.29 sur Ubuntu fait le tour. Pas un bug en tant que tel, plus une fonctionnalité :)
bwduncan
1
Merci! C'est exactement ce dont j'avais besoin pour un script système.
vog
12

La méthode la plus précise que je connaisse consiste à utiliser le résultat 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 permet de visualiser 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)

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

Je trouve que consulter / proc / partitions est le 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 la majeur 8, mineure 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

Notez le 8, 1 avant l’horodatage.

Il est important de comprendre / de se rappeler que le nom d’un fichier de périphérique tel que / dev / sda1 n’est qu’une étiquette. Les nombres majeur et mineur sont les valeurs significatives et importantes du fichier de périphérique. Si vous êtes curieux, consultez l'utilitaire mknod (1) utilisé pour créer les fichiers de périphérique. Je pourrais créer une nouvelle entrée / dev appelée aardvark avec majeur 8, mineure 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 le résultat de la commande mount ou le contenu de / proc / mounts et que nous voyons:

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

df -h montre:

/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 en mode bloc sont les nombres majeurs et mineurs - et non l'étiquette du fichier de périphérique - et que l'appel système lstat () est le meilleur moyen de interroger ces valeurs.

En guise de dernier commentaire, je viens de relire votre question pour m'assurer de bien y répondre et j'ai compris que vous demandiez quelle étiquette de périphérique source s'afficherait dans / proc / mounts pour un montage bind. Ce serait la même étiquette de périphérique source que celle utilisée dans l'appel originel de mount (2) pour la source du 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 (comme ci-dessus). Remarquez que je vais monter deux fois le même système de fichiers. 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 étant donné que / mnt1 et / mnt2 ont le même système de fichiers monté, un répertoire 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 / foo / ... bind est identique à la valeur fournie à l'origine dans l'appel de 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 partie ne répond pas du tout à votre question, mais le supprimer semblait une perte de temps. Peut-être que ça va aider quelqu'un d'autre.

Bonne chance.

PS Ne pas oublier 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 bloc source. Je ne sais pas ce qui sera retourné en tant que périphérique dans la sortie de statistiques, juste pour ce que cela vaut.

merle
la source
1
La première partie m'aide certainement à comprendre la dernière partie.
StrongBad
Cette réponse ne fonctionne pas pour les chemins tmpfs. Vous ne trouverez pas le st_dev mineur, majeur sur / proc / partitions.
Mbello
@mbello Comme je l'ai mentionné à la fin de ma réponse, cette méthode ne fonctionnera pas et ne fonctionnera pas pour les systèmes de fichiers dépourvus de périphérique de sauvegarde, comme tmpfs montés.
Etherfish
2

É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> imprimera uniquement le point de montage de manière arrondie (bien que vous deviez vérifier le code de sortie pour détecter sans erreur une erreur de permission; 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 la création 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

Tu es grand comment ?

$ 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 des onglets de ma distribution ne comprend même pas cela correctement. Nous allons donc utiliser un caractère générique comme exemple de point de montage avec des retours chariot, 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: -
Carey Underwood
la source
1
Le balisage <kbd> est utilisé pour une clé unique plutôt que pour une commande complète. Cela ne semble pas mieux ainsi, à mon humble avis.
Tomasz