Determine em que dispositivo um diretório está localizado

49

Se eu fizer

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

a entrada /proc/mountsé

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

que é o dispositivo que é montado /homee não é facilmente dedutível a partir de $PWDque é /test. Como posso determinar qual dispositivo (por exemplo, / dev / sda2) será exibido /proc/mountsem geral, dado que a montagem de ligação pode estar em um diretório / arquivo potencialmente "obscurecido" por links simbólicos, outras montagens de ligação, etc.?

StrongBad
fonte

Respostas:

49

Se entendi sua pergunta, você quer saber qual dispositivo foi usado para uma determinada montagem. Para isso, você pode usar o 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

Para descobrir em qual dispositivo um arquivo / diretório específico está localizado, forneça o arquivo como argumento df. Usando seu exemplo:

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

Você também pode usar o 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)

O diretório montado para cada dispositivo é o terceiro argumento na saída acima. Então, para o dispositivo /dev/sda1seria /boot. Os outros dispositivos estão usando o LVM (Logical Volume Management) e precisariam ser consultados para saber qual dispositivo real está sendo usado pelo LVM.

slm
fonte
Se $PWD(que é o que estou montando) estiver enterrado em uma série de links simbólicos, montagens de ligação, etc., eu precisaria examinar recursivamente o caminho para obter pontos de montagem.
StrongBad
Com montagens de ligação, apesar do que aparece na /proc/mounts"coisa" montada, pelo menos em minha mente, não é o dispositivo, é o diretório / arquivo.
StrongBad
@StrongBad - o que readlink -f /mntmostra?
Slm
2
@StrongBad se você precisar lidar com a determinação do ponto / dispositivo de montagem quando obscurecido por links simbólicos, coloque isso na sua pergunta. Tornará muito mais fácil obter a resposta certa.
8104 Patrick
readlink -f /mnt/mnt
StrongBad
29

No Linux, temos findmntde util-linuxfeita exatamente para este

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

A vantagem de outras soluções é que ainda funcionará se os caminhos forem obscurecidos por links simbólicos ou montagens de ligação duplicadas.

rudimeier
fonte
Isso não funciona para mim. Ele mostra a fonte de todas as montagens no sistema. findmnt do util-linux 2.23.2
bwduncan
@bwduncan para mim funciona com 2.23.2. Talvez um bug? Você poderia tentar a versão mais recente 2.29.2?
Rudimeier
2.29 no Ubuntu faz o truque. Não é um bug, como tal, mais uma característica :)
bwduncan
11
Obrigado! Era exatamente isso que eu precisava para um script do sistema.
vog
11

O método mais preciso que conheço é usar a saída da chamada do sistema lstat (). Especificamente, o campo st_dev. Existe um utilitário de linha de comando, stat (1), que pode ser usado para ver essas informações. Por exemplo, a saída de "stat / etc / issue" no meu 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)

Observe a terceira linha, primeiro campo, "Dispositivo". Aqui lista 801h. Esse valor pode ser separado em dois bytes, 8 e 1. O primeiro byte é conhecido como o número principal, o segundo byte é o número menor. Portanto, o próximo passo é descobrir qual é o dispositivo maior 8, menor 1.

Acho consultoria / proc / partições para ser o mais rápido. No meu caso, / proc / partitions tem o conteúdo:

major minor  #blocks  name

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

É bastante claro a partir dessa saída que 8 maiores, 1 menor é sda1. Podemos confirmar isso com um ls -l / dev / sda1

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

Observe o 8, 1 antes do carimbo de data.

É importante entender / lembrar que o nome de um arquivo de dispositivo como / dev / sda1 é apenas um rótulo. Os números principais e secundários são os valores significativos e importantes do arquivo do dispositivo. Se você ficar curioso, consulte o utilitário mknod (1) usado para criar arquivos de dispositivo. Eu poderia criar uma nova entrada / dev chamada aardvark com 8 maiores, 18 menores com a seguinte sintaxe:

mknod /dev/aardvark b 8 18

Então, eu poderia montá-lo facilmente:

mount /dev/aardvark /mnt

e, se observarmos a saída do comando mount ou o conteúdo de / proc / mounts e veremos:

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

df -h mostra:

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

De qualquer forma, o objetivo de tudo isso é ilustrar que os detalhes importantes para identificar um dispositivo de bloco são os números principais e secundários - não o rótulo do arquivo do dispositivo - e que o uso da chamada de sistema lstat () é a melhor maneira de consultar esses valores.

Como último comentário, apenas reli sua pergunta para ter certeza de que estava respondendo e percebi que você estava perguntando qual rótulo de dispositivo de origem apareceria em / proc / mounts para uma montagem de ligação. Esse seria o mesmo rótulo do dispositivo de origem usado na chamada original mount (2) para a origem do ponto de montagem do sistema de arquivos para a montagem de ligação. Talvez um exemplo ajude:

Eu tenho / dev / sdb2 e / dev / aardvark (o mesmo que acima). Ambos são 8 maiores, 18 menores. Note que montarei o mesmo sistema de arquivos duas vezes. Eu faço o seguinte:

mkdir /mnt1 /mnt2 /foo

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

Observe que eu criei o diretório em / mnt1. Mas como / mnt1 e / mnt2 têm o mesmo sistema de arquivos montado, algo também poderá ser alcançado através de / mnt2.

mkdir /mnt1/somedir

mkdir /foo/left /foo/right

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

Agora, se verificarmos / proc / mounts, veremos:

/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

O rótulo do dispositivo de origem nas montagens de ligação / foo / ... é o mesmo que o valor originalmente fornecido na chamada mount (2) do sistema de arquivos. Lembre-se, / dev / aardvark e / dev / sdb2 no meu exemplo são o mesmo dispositivo.

Sei que acabei de escrever um romance e a primeira metade não responde realmente à sua pergunta, mas parecia um desperdício excluí-la. Talvez ajude alguém.

Boa sorte.

PS Lembre-se de que alguns sistemas de arquivos são baseados em rede - como NFS ou CIFS - ou são procfs ou sysfs, como virtuais, e não possuem um dispositivo de bloqueio de origem. Não sei o que será retornado como o dispositivo na saída stat, apenas pelo que vale a pena.

etherfish
fonte
11
A primeira parte definitivamente me ajuda a entender a última parte.
StrongBad
Esta resposta não funciona para caminhos tmpfs. Você não encontrará o st_dev minor, major em / proc / partitions.
mbello 10/02
@ mello Como eu mencionei no final da minha resposta, esse método não funciona e não pode funcionar em sistemas de arquivos que não possuem dispositivo de suporte - como montagens tmpfs.
etherfish
2

Dados os seguintes pontos de montagem típicos:

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

stat --format %m <path> imprimirá apenas o ponto de montagem de uma maneira que pode ser arredondada (embora você precise verificar o código de saída para detectar inequivocamente um erro de permissão; as abordagens da tabela de montagem ganham aqui):

$ 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

Os links simbólicos tomam um pouco de cuidado, como de costume:

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

E, claro, lembre-se de usar aspas ao criar scripts. Considere um caminho de ponto de montagem com espaços e assim:

$ 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

Quão grande você é ?

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

A conclusão da guia da minha distribuição não está correta, por isso, faremos um curinga neste exemplo de ponto de montagem com retornos de carro e avanço de linha e lotes de espaços:

$ 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
fonte
11
A marcação <kbd> é usada para uma única chave, em vez de um comando inteiro. Não parece melhor assim, na minha humilde opinião.
Tomasz