GNU/Linux >> Tutoriales Linux >  >> Linux

Listar solo montajes enlazados

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 yo sé, las siguientes secuencias de comandos conducen a estados del sistema esencialmente idénticos en lo que respecta al kernel:

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é montajes eran montajes vinculados es el registro de mount comandos dejados en /etc/mtab . Una operación de montaje de vinculación se indica mediante el bind montar opción (lo que hace que se ignore el tipo de sistema de archivos). Pero mount 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 realizar su propio filtrado.

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

Tenga en cuenta que /etc/mtab solo es útil aquí si es un archivo de texto mantenido por mount . Algunas distribuciones configuran /etc/mtab como enlace simbólico a /proc/mounts en cambio; /proc/mounts es mayormente equivalente a /etc/mtab pero tiene algunas diferencias, una de las cuales no es el seguimiento de los montajes de vinculación.

Una pieza de información que es retenida por el kernel, pero que no se muestra en /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 montajes de vinculación:

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

En /proc/mounts , las entradas para /mnt/one y /mnt/partial tener el mismo dispositivo, el mismo tipo de sistema de archivos y las mismas opciones. La información que /mnt/partial solo muestra la parte del sistema de archivos que está arraigada en /sub es visible en la información del punto de montaje por proceso en /proc/$pid/mountinfo (columna 4). Las entradas 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

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

El kernel no maneja montajes de enlace diferentes de los normales monta después del hecho. Los únicos difieren en lo que sucede mientras mount corre.

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 núcleo busca un controlador de sistema de archivos para el tipo de sistema de archivos especificado (si omite -t o usa -t auto mount adivina 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 mediante un par de números mayor: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í. (nodev por ejemplo, es una opción en el punto de montaje, no en el sistema de archivos. Puede tener un montaje de enlace con nodev y uno sin)

Si realiza un montaje de vinculación (por ejemplo, con mount --bind /a /b ) ocurre lo siguiente:

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

(Omitiré 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 haces un enlace duro sucede lo siguiente:

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

Como puede ver, el archivo creado y el enlace físico son indistinguibles:

$ 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 fijos a un archivo comparando los números de inodo, puede identificar todos los montajes en un sistema de archivos comparando los números mayor:menor de montajes.

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

La siguiente secuencia de comandos de Python enumera todos los montajes de enlace. Asume 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))

Linux
  1. ¿Una montura de unión?

  2. ¿Montar un sistema de archivos de solo lectura y redirigir las escrituras a la RAM?

  3. ¿Por qué el montaje no respeta la opción de solo lectura para los montajes de enlace?

  4. Monte el archivo zip como un sistema de archivos de solo lectura

  5. ¿Montar un nuevo sistema de archivos afecta a los montajes de enlace no recursivos?

¿Cómo montar un sistema de archivos, asignando ID de usuario?

¿Montar un sistema de archivos Cifs directamente o a través de Fstab?

Cómo enumerar solo directorios en Linux

Depuración de problemas de fstab al reiniciar

¿Cómo montar un sistema de archivos en un entorno de solo lectura?

No se puede montar el disco (VFS:no se puede encontrar el sistema de archivos ext4)