Lista solo montajes de enlace

24

En lugar de usar mount | grep, me gustaría usar mount -l -t bind, pero eso no funciona y -t nonemuestra todas las monturas.

l0b0
fuente

Respuestas:

28

Los montajes de enlace no son un tipo de sistema de archivos, ni un parámetro de un sistema de archivos montado; son parámetros de una operación de montaje . Hasta donde sé, las siguientes secuencias de comandos conducen a estados del sistema esencialmente idénticos en lo que respecta al núcleo:

mount /dev/foo /mnt/one; mount --bind /mnt/one /mnt/two
mount /dev/foo /mnt/two; mount --bind /mnt/two /mnt/one

Entonces, la única forma de recordar qué monturas eran monturas de unión es el registro de mountcomandos que quedan /etc/mtab. La opción debind montaje indica una operación de montaje de enlace (que hace que se ignore el tipo de sistema de archivos). Pero no tiene la opción de enumerar solo los sistemas de archivos montados con un conjunto particular de conjuntos de opciones. Por lo tanto, debe hacer su propio filtrado.mount

mount | grep -E '[,(]bind[,)]'
</etc/mtab awk '$4 ~ /(^|,)bind(,|$)/'

Tenga en cuenta que /etc/mtabsolo es útil aquí si es un archivo de texto mantenido por mount. Algunas distribuciones configuradas /etc/mtabcomo un enlace simbólico en su /proc/mountslugar; /proc/mountses principalmente equivalente /etc/mtabpero tiene algunas diferencias, una de las cuales no es el seguimiento de los montajes de enlace.

Una parte de la información que retiene el núcleo, pero que no se muestra /proc/mounts, es cuando un punto de montaje solo muestra una parte del árbol de directorios en el sistema de archivos montado. En la práctica, esto sucede principalmente con los montajes de unión:

mount --bind /mnt/one/sub /mnt/partial

En /proc/mounts, las entradas para /mnt/oney /mnt/partialtienen el mismo dispositivo, el mismo tipo de sistema de archivos y las mismas opciones. La información que /mnt/partialsolo muestra la parte del sistema de archivos en la que está rooteado /subes visible en la información del punto de montaje por proceso en /proc/$pid/mountinfo(columna 4). Las entradas allí se ven así:

12 34 56:78 / /mnt/one rw,relatime - ext3 /dev/foo rw,errors=remount-ro,data=ordered
12 34 56:78 /sub /mnt/partial rw,relatime - ext3 /dev/foo rw,errors=remount-ro,data=ordered
Gilles 'SO- deja de ser malvado'
fuente
1
@Gilles En realidad, puedes hacer esto simplemente usando findmnt | fgrep [como se explica aquí .
aculich
@Gilles ¿Qué mount --versionestás usando para registrar cualquier bindinformación /etc/mtab? Estoy usando la versión 2.20.1 y miré las últimas fuentes y en ninguno de los casos veo información de enlace grabada en cualquier lugar que te permita buscar bind. Por otro lado, lo que sugerí en mi respuesta en realidad enumera los montajes de enlace creados con --bindla bind opción .
aculich
@aculich </etc/mtab awk …es compatible con POSIX (no recuerdo si es compatible con Bourne). Por favor revise sus hechos. Puedo confirmar que /etc/mtabtiene la bindopción para un sistema de archivos montado mount --bind /source /targeten Debian estable (montaje desde util-linux-ng 2.17.2).
Gilles 'SO- deja de ser malvado'
@Gilles Eliminé mi comentario errante para eliminar la confusión. Tienes razón, de hecho es compatible con POSIX. También ahora entiendo la razón por la que vemos un comportamiento diferente de mounty /etc/mtab. Está utilizando Debian estable, que tiene la versión anterior de util-linux-ng; Estoy usando Debian testing que tiene una versión más nueva que ya no parece tener el mismo /etc/mtabcomportamiento, lo que es quizá la razón por @rozcietrzewiacz no vieron binden en /etc/mtabsi su distribución también está utilizando una versión más reciente?
aculich
1
@aculich Deberías publicar findmntcomo respuesta. Por cierto, solo funciona si el directorio de destino no es otro punto de montaje. Pruebe por ejemplosudo mount --bind / foo && findmnt | grep foo
l0b0
21

Tal vez esto podría hacer el truco:

findmnt | grep  "\["

Ejemplo:

$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep  "\["
│ └─/tmp/foo                     /dev/sda2[/media] ext4            rw,relatime,data=ordered
olopopo
fuente
1
Aparentemente, esto solo funciona cuando se monta un subdirectorio de un punto de montaje. Si /está montado en enlace, por ejemplo, la salida no tiene un [...].
Muru
8

El núcleo no maneja montajes de enlace diferentes de los montajes normales después del hecho. Lo único difiere en lo que sucede mientras se mountejecuta.

Cuando monta un sistema de archivos (por ejemplo, con mount -t ext4 /dev/sda1 /mnt) el núcleo (un poco simplificado) realiza tres pasos:

  1. El kernel busca un controlador de sistema de archivos para el tipo de sistema de archivos especificado (si omite -to utiliza -t auto mountadivina el tipo por usted y proporciona el tipo adivinado al kernel)
  2. El kernel le indica al controlador del sistema de archivos que acceda al sistema de archivos utilizando la ruta de origen y las opciones proporcionadas. En este punto, el sistema de archivos solo se identifica por un par mayor: número menor.
  3. El sistema de archivos está vinculado a una ruta (el punto de montaje). El kernel también usa algunas de las opciones de montaje aquí. ( nodevpor ejemplo, es una opción en el punto de montaje, no en el sistema de archivos. Puede tener un montaje de enlace con nodevy uno sin)

Si realiza un montaje de enlace (por ejemplo, con mount --bind /a /b), sucede lo siguiente:

  1. El núcleo resuelve qué sistema de archivos contiene la ruta de origen y la ruta relativa desde el punto de montaje al directorio.
  2. El sistema de archivos está vinculado al nuevo punto de montaje utilizando las opciones y la ruta relativa.

(Saltaré mount --move, porque no es relevante para la pregunta).

Esto es bastante similar a cómo se crean los archivos en Linux:

  1. El núcleo resuelve qué sistema de archivos es responsable del directorio en el que se debe crear el archivo.
  2. Se crea un nuevo archivo en el sistema de archivos. En este punto, el archivo solo tiene un número de inodo.
  3. El nuevo archivo está vinculado a un nombre de archivo en el directorio.

Si crea un enlace duro, sucede lo siguiente:

  1. El kernel resuelve el número de inodo del archivo fuente.
  2. El archivo está vinculado al nombre del archivo de destino.

Como puede ver, el archivo creado y el enlace duro no se pueden distinguir:

$ touch first
$ ln first second
$ ls -li
1184243 -rw-rw-r-- 2 cg909 cg909 0 Feb 20 23:56 /tmp/first
1184243 -rw-rw-r-- 2 cg909 cg909 0 Feb 20 23:56 /tmp/second

Pero , como puede identificar todos los enlaces duros a un archivo al comparar los números de inodo, puede identificar todos los montajes a un sistema de archivos al comparar el mayor: números menores de montajes.

Puede hacerlo con findmnt -o TARGET,MAJ:MINo directamente mirando /proc/self/mountinfo( consulte la documentación del kernel de Linux para obtener más información ).

El siguiente script de Python enumera todos los montajes de enlace. Se supone que el punto de montaje más antiguo con la ruta relativa más corta a la raíz del sistema de archivos montado es el montaje original.

#!/usr/bin/python3

import os.path, re
from collections import namedtuple

MountInfo = namedtuple('MountInfo', ['mountid', 'parentid', 'devid', 'root', 'mountpoint', 'mountoptions', 'extra', 'fstype', 'source', 'fsoptions'])

mounts = {}

def unescape(string):
    return re.sub(r'\\([0-7]{3})', (lambda m: chr(int(m.group(1), 8))), string)

with open('/proc/self/mountinfo', 'r') as f:
    for line in f:
        # Parse line
        mid, pid, devid, root, mp, mopt, *tail = line.rstrip().split(' ')
        extra = []
        for item in tail:
            if item != '-':
                extra.append(item)
            else:
                break
        fstype, src, fsopt = tail[len(extra)+1:]
        # Save mount info
        mount = MountInfo(int(mid), int(pid), devid, unescape(root), unescape(mp), mopt, extra, fstype, unescape(src), fsopt)
        mounts.setdefault(devid, []).append(mount)

for devid, mnts in mounts.items():
    # Skip single mounts
    if len(mnts) <= 1:
        continue
    # Sort list to get the first mount of the device's root dir (if still mounted)
    mnts.sort(key=lambda x: x.root)
    src, *binds = mnts
    # Print bind mounts
    for bindmount in binds:
        if src.root == bindmount.root:
            srcstring = src.mountpoint
        else:
            srcstring = src.mountpoint+':/'+os.path.relpath(bindmount.root, src.root)
        print('{0} -> {1.mountpoint} ({1.mountoptions})'.format(srcstring, bindmount))
cg909
fuente
0
unset DONE1FSES
FSES=$(findmnt -vUPno SOURCE,FSROOT,TARGET,MAJ:MIN)
FSES=${FSES//MAJ:MIN/MAJ_MIN}
while read SEARCH1FS
do
  unset DONE2FSES
  eval "$SEARCH1FS"
  SEARCH1SOURCE=$SOURCE
  SEARCH1FSROOT=$FSROOT
  SEARCH1TARGET=$TARGET
  SEARCH1MAJMIN=$MAJ_MIN

  FS1WASHANDLED=0
  while read DONE1FS 
  do
    if [[ $DONE1FS == $MAJ_MIN ]]
    then
      FS1WASHANDLED=1
      break
    fi
  done < <(echo "$DONE1FSES")


  if [[ ($SEARCH1FSROOT == /) && ($FS1WASHANDLED == 0) ]]
  then
  DONE1FSES+=$MAJ_MIN$'\n'
  while read SEARCH2FS
  do
    eval "$SEARCH2FS"
    SEARCH2SOURCE=$SOURCE
    SEARCH2FSROOT=$FSROOT
    SEARCH2TARGET=$TARGET
    SEARCH2MAJMIN=$MAJ_MIN

    FS2WASHANDLED=0
    while read DONE2FS 
    do
      if [[ $DONE2FS == $SEARCH2FS ]]
      then
        FS2WASHANDLED=1
        break
      fi
    done < <(echo "$DONE2FSES")

    if [[ ($SEARCH1MAJMIN == $SEARCH2MAJMIN)  && ($SEARCH1TARGET != $SEARCH2TARGET )  && ($FS2WASHANDLED == 0 ) ]]
    then
      DONE2FSES+=$SEARCH2FS$'\n'
      echo "$SEARCH1TARGET$SEARCH2FSROOT   --> $SEARCH2TARGET"
    fi

  done < <(echo "$FSES")


  fi
done   < <(echo "$FSES")
n3rdopolis
fuente
0

Esto es similar a la otra respuesta findmnt, pero evita el problema de formato.

Para mostrar todas las submontajes:

findmnt --kernel -n --list | grep '\['

Para mostrar todos los submontes de sistemas de archivos de tipo ext4:

findmnt --kernel -t ext4 -n --list | grep '\['

Para mostrar todos los montajes, excepto los submontes:

findmnt --kernel -n --list | grep -v '\['

Para mostrar todos los montajes de sistemas de archivos de tipo ext4, excluyendo los submontajes:

findmnt --kernel -t ext4 -n --list | grep -v '\['

El "-n" elimina los encabezados y el "--list" elimina las líneas del formato "árbol".

Probado en el tramo Debian.

sg23
fuente