Determine en qué dispositivo se ubica un directorio

50

Si lo hago

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

la entrada en /proc/mountses

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

cuál es el dispositivo que está montado /homey no es fácilmente deducible de $PWDcuál es /test. ¿Cómo puedo determinar qué dispositivo (es decir, / dev / sda2) se mostrará /proc/mountsen general dado que el montaje de enlace puede estar en un directorio / archivo que está potencialmente "oculto" por enlaces simbólicos, otros montajes de enlace, etc.

Fuerte
fuente

Respuestas:

49

Si entiendo su pregunta, desea saber qué dispositivo se utilizó para un montaje determinado. Para esto puedes usar el 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 encontrar en qué dispositivo se encuentra un archivo / directorio en particular, proporcione el archivo como argumento para df. Usando tu ejemplo:

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

También puedes usar el 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)

El directorio montado para cada dispositivo es el tercer argumento en la salida anterior. Entonces, para el dispositivo /dev/sda1sería /boot. Los otros dispositivos están haciendo uso de LVM (Logical Volume Management) y tendrían que ser consultados para saber qué dispositivo real está utilizando LVM.

slm
fuente
Si $PWD(que es lo que estoy montando) está enterrado en una serie de enlaces simbólicos, montajes de enlace, etc., entonces necesitaría examinar recursivamente la ruta para ver los puntos de montaje.
StrongBad
Con los montajes de enlace a pesar de lo que aparece en /proc/mountsla "cosa" que está montada, al menos en mi mente, no es el dispositivo, es el directorio / archivo.
StrongBad
@StrongBad: ¿qué readlink -f /mntmuestra?
slm
2
@StrongBad si tiene que lidiar con la determinación del punto de montaje / dispositivo cuando está oculto por enlaces simbólicos, debe poner eso en su pregunta. Será mucho más fácil obtener la respuesta correcta.
Patrick
readlink -f /mntda/mnt
StrongBad
30

En Linux hemos findmntde util-linuxhecho exactamente para este

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

La ventaja de otras soluciones es que aún funciona si las rutas están oscurecidas por enlaces simbólicos o montajes de enlace duplicados.

rudimeier
fuente
Esto no funciona para mi. Muestra la fuente de cada montaje en el sistema. findmnt de util-linux 2.23.2
bwduncan
@bwduncan para mí funciona con 2.23.2. Tal vez un error? ¿Podrías probar la última versión 2.29.2?
rudimeier
2.29 en Ubuntu hace el truco. No es un error como tal, más una característica :)
bwduncan
1
¡Gracias! Eso es exactamente lo que necesitaba para un script de sistema.
vog
12

El método más preciso que conozco es utilizar la salida de la llamada al sistema lstat (). Específicamente, el campo st_dev. Hay una utilidad de línea de comando, stat (1) que se puede usar para ver esta información. Por ejemplo, la salida de "stat / etc / issue" en mi computadora portátil:

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 la tercera línea, primer campo, "Dispositivo". Aquí enumera 801h. Ese valor se puede separar en dos bytes, 8 y 1. El primer byte se conoce como el número mayor, el segundo byte es el número menor. Entonces, el siguiente paso es descubrir qué dispositivo es el mayor 8, el menor 1.

Encuentro consultoría / proc / particiones para ser el más rápido. En mi caso, / proc / partitions tiene el contenido:

major minor  #blocks  name

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

Está bastante claro a partir de esa salida que el mayor 8, el menor 1 es sda1. Podemos confirmar esto con un ls -l / dev / sda1

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

Observe el 8, 1 antes del sello de fecha.

Es importante entender / recordar que el nombre de un archivo de dispositivo como / dev / sda1 es solo una etiqueta. Los números mayores y menores son los valores significativos e importantes del archivo del dispositivo. Si siente curiosidad, consulte la utilidad mknod (1) utilizada para crear archivos de dispositivo. Podría crear una nueva entrada / dev llamada aardvark con mayor 8, menor 18 con la siguiente sintaxis:

mknod /dev/aardvark b 8 18

Entonces, podría montarlo fácilmente:

mount /dev/aardvark /mnt

y, si miramos la salida del comando mount o el contenido de / proc / mounts y vemos:

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

df -h muestra:

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

De todos modos, el objetivo de todo esto es ilustrar que los detalles importantes para identificar un dispositivo de bloque son los números mayores y menores, no la etiqueta del archivo del dispositivo, y que usar la llamada al sistema lstat () es la mejor manera de consultar esos valores.

Como último comentario, acabo de volver a leer su pregunta para asegurarme de que la estaba respondiendo y me di cuenta de que estaba preguntando qué etiqueta de dispositivo fuente aparecería en / proc / montes para un montaje de enlace. Esa sería la misma etiqueta del dispositivo fuente que se usó en la llamada original mount (2) para la fuente del punto de montaje del sistema de archivos para el montaje de enlace. Quizás un ejemplo ayudaría:

Tengo / dev / sdb2 y / dev / aardvark (lo mismo que arriba). Ambos son principales 8, menores 18. Nota, montaré el mismo sistema de archivos dos veces. Hago lo siguiente:

mkdir /mnt1 /mnt2 /foo

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

Observe que hago el directorio somedir en / mnt1. Pero como / mnt1 y / mnt2 tienen el mismo sistema de archivos montado, también se podrá acceder a somedir a travé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

Ahora, si verificamos / proc / monturas, vemos:

/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

La etiqueta del dispositivo de origen en los montajes de enlace / foo / ... es el mismo que el valor suministrado originalmente en la llamada mount (2) del sistema de archivos. Recuerde, / dev / aardvark y / dev / sdb2 en mi ejemplo son el mismo dispositivo.

Me doy cuenta de que acabo de escribir una novela y la primera mitad realmente no responde a tu pregunta, pero me pareció un desperdicio eliminarla. Quizás ayude a alguien más.

Buena suerte.

PD Tenga en cuenta que algunos sistemas de archivos se basan en la red, como NFS o CIFS, o son virtuales, como procfs o sysfs y no tienen un dispositivo de bloque de origen. No sé qué se devolverá como dispositivo en la salida de estadísticas, solo por lo que vale.

Etherfish
fuente
1
La primera parte definitivamente me ayuda a entender la última parte.
StrongBad
Esta respuesta no funciona para las rutas tmpfs. No encontrará el st_dev menor, mayor en / proc / particiones.
mbello
@mbello Como mencioné al final de mi respuesta, este método no funcionará y no puede funcionar para sistemas de archivos que no tienen un dispositivo de respaldo, como los montajes tmpfs.
Etherfish
2

Dados los siguientes puntos de montaje típicos:

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

stat --format %m <path> imprimirá solo el punto de montaje de forma redonda y atrapable (aunque debe verificar el código de salida para detectar inequívocamente un error de permiso; los enfoques de la tabla de montaje ganan aquí):

$ 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

Los enlaces simbólicos se cuidan un poco como de costumbre:

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

Y, por supuesto, recuerde usar comillas cuando haga scripts. Considere una ruta de punto de montaje con espacios y tal:

$ 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é tan grande es que?

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

La finalización de la pestaña de mi distribución ni siquiera lo hace bien, por lo que simplemente pondremos comodín este ejemplo de punto de montaje con retornos de carro y saltos de línea y espacios:

$ 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
fuente
1
El marcado <kbd> se usa para una sola tecla, en lugar de un comando completo. No se ve mejor así, en mi humilde opinión.
Tomasz