Elenca solo i collegamenti di binding


24

Piuttosto che usare mount | grep, mi piacerebbe usare mount -l -t bind, ma non funziona e -t nonemostra tutti i supporti.

Risposte:


28

I montaggi di bind non sono un tipo di filesystem, né un parametro di un filesystem montato; sono parametri di un monte operazione . Per quanto ne so, le seguenti sequenze di comandi portano a stati di sistema sostanzialmente identici per quanto riguarda il kernel:

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

Quindi l'unico modo per ricordare quali erano i montaggi di bind mount è il registro dei mountcomandi rimasti /etc/mtab. Un'operazione di bind mount è indicata dall'opzionebind mount (che fa ignorare il tipo di filesystem). Ma non ha alcuna opzione per elencare solo i filesystem montati con un particolare set di set di opzioni. Pertanto è necessario eseguire il proprio filtro.mount

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

Nota che /etc/mtabè utile qui solo se è un file di testo gestito da mount. Alcune distribuzioni impostate invece /etc/mtabcome link simbolici /proc/mounts; /proc/mountsè per lo più equivalente /etc/mtabma presenta alcune differenze, una delle quali non sta monitorando i mount bind.

Un'informazione che viene mantenuta dal kernel, ma non mostrata in /proc/mounts, è quando un mount point mostra solo una parte dell'albero delle directory sul filesystem montato. In pratica ciò accade principalmente con i montaggi di associazione:

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

In /proc/mounts, le voci per /mnt/onee /mnt/partialhanno lo stesso dispositivo, lo stesso tipo di filesystem e le stesse opzioni. Le informazioni che /mnt/partialmostrano solo la parte del filesystem su cui è stato effettuato il root /subsono visibili nelle informazioni sul punto di montaggio per processo in /proc/$pid/mountinfo(colonna 4). Le voci sembrano così:

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

1
@Gilles In realtà, puoi farlo semplicemente usando findmnt | fgrep [come spiegato qui .
aculich,

@Gilles Cosa mount --versionstai usando per registrare qualsiasi bindinformazione /etc/mtab? Sto usando la versione 2.20.1 e ho guardato alle ultime fonti e in nessun caso vedo le informazioni di bind registrate ovunque che ti permetterebbero di fare grep bind. D'altra parte, ciò che ho suggerito nella mia risposta in realtà elenca i montaggi di bind creati con --binde usando l' bind opzione .
aculich

@aculich </etc/mtab awk …è conforme a POSIX (ho dimenticato se è supportato a Bourne). Si prega di controllare i fatti. Posso confermare che /etc/mtabha l' bindopzione per un filesystem montato mount --bind /source /targetsu Debian stable (mount da util-linux-ng 2.17.2).
Gilles 'SO- smetti di essere malvagio' il

@Gilles Ho cancellato il mio commento errato per rimuovere la confusione. Hai ragione, è effettivamente conforme a POSIX. Inoltre ora capisco il motivo per cui stiamo assistendo a comportamenti diversi di mounte /etc/mtab. Stai usando Debian stable che ha la versione precedente di util-linux-ng; Sto usando Debian testing che ha una versione più recente che non sembra più avere lo stesso /etc/mtabcomportamento, che è forse il motivo per cui @rozcietrzewiacz non ha visto bindin in /etc/mtabse la sua distribuzione è anche utilizzando una versione più recente?
aculich,

1
@aculich Dovresti postare findmntcome risposta. Funziona solo se la directory di destinazione non è un altro punto di montaggio, comunque. Prova ad esempiosudo mount --bind / foo && findmnt | grep foo
l0b0

21

Forse questo potrebbe fare il trucco:

findmnt | grep  "\["

Esempio:

$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep  "\["
│ └─/tmp/foo                     /dev/sda2[/media] ext4            rw,relatime,data=ordered

1
Apparentemente, funziona solo quando è montata una sottodirectory di un mountpoint. Se esso /stesso è montato su bind, ad esempio, l'output non ha a [...].
Muru,

8

Il kernel non gestisce i montaggi di bind diversi dai montaggi normali dopo il fatto. L'unica differenza in ciò che accade mentre mountcorre.

Quando monti un filesystem (es. Con mount -t ext4 /dev/sda1 /mnt) il kernel (un po 'semplificato) esegue tre passaggi:

  1. Il kernel cerca un driver di filesystem per il tipo di filesystem specificato (se ometti -to usi -t auto mountindovina il tipo per te e fornisci il tipo indovinato al kernel)
  2. Il kernel indica al driver del filesystem di accedere al filesystem usando il percorso sorgente e tutte le opzioni fornite. A questo punto il filesystem è identificato solo da una coppia di numeri maggiore: minore.
  3. Il filesystem è associato a un percorso (il mountpoint). Il kernel usa anche alcune delle opzioni di mount qui. ( nodevad esempio è un'opzione sul mountpoint, non sul filesystem. Puoi avere un mount bind con nodeve uno senza)

Se si esegue un attacco di associazione (ad es. Con mount --bind /a /b), si verifica quanto segue:

  1. Il kernel risolve quale filesystem contiene il percorso sorgente e il percorso relativo dal mountpoint alla directory.
  2. Il filesystem è associato al nuovo mountpoint usando le opzioni e il relativo percorso.

(Salto mount --move, perché non è rilevante per la domanda.)

Questo è abbastanza simile al modo in cui i file vengono creati su Linux:

  1. Il kernel risolve quale filesystem è responsabile della directory in cui il file dovrebbe essere creato.
  2. Viene creato un nuovo file nel filesystem. A questo punto il file ha solo un numero di inode.
  3. Il nuovo file è collegato a un nome file nella directory.

Se si crea un collegamento reale, accade quanto segue:

  1. Il kernel risolve il numero di inode del file sorgente.
  2. Il file è collegato al nome file di destinazione.

Come puoi vedere, il file creato e l'hard link sono indistinguibili:

$ 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

Tuttavia , poiché è possibile identificare tutti i collegamenti fisici a un file confrontando i numeri di inode, è possibile identificare tutti i montaggi su un filesystem confrontando i principali: minori numeri di montaggi.

Puoi farlo con findmnt -o TARGET,MAJ:MINo guardando direttamente /proc/self/mountinfo( vedi la documentazione del kernel Linux per maggiori informazioni ).

Il seguente script Python elenca tutti i mount di bind. Presuppone che il mount point più vecchio con il percorso relativo più breve alla radice del file system montato sia il mount originale.

#!/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))

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")

0

È simile all'altra risposta findmnt, ma evita il problema di formattazione.

Per mostrare tutti i submount:

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

Per mostrare tutti i sotto-montaggi di filesystem di tipo ext4:

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

Per mostrare tutti i mount esclusi i submount:

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

Per mostrare tutti i mount dei filesystem di tipo ext4 esclusi i submount:

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

"-N" rimuove le intestazioni e "--list" rimuove le linee del formato "albero".

Testato su tratto Debian.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.