I bind mount non sono un tipo di filesystem, né un parametro di un filesystem montato; sono i parametri di un'operazione di montaggio . Per quanto ne so, le seguenti sequenze di comandi portano a stati di sistema essenzialmente 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 mount erano bind mount è il log di mount
comandi lasciati in /etc/mtab
. Un'operazione di bind mount è indicata da bind
mount opzione (che fa sì che il tipo di filesystem venga ignorato). Ma mount
non ha alcuna opzione per elencare solo i filesystem montati con un particolare set di set di opzioni. Pertanto è necessario eseguire il proprio filtraggio.
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 impostano /etc/mtab
come collegamento simbolico a /proc/mounts
invece; /proc/mounts
è per lo più equivalente a /etc/mtab
ma presenta alcune differenze, una delle quali non è il monitoraggio dei montaggi dei bind.
Una parte di informazione conservata dal kernel, ma non mostrata in /proc/mounts
, è quando un punto di montaggio mostra solo una parte dell'albero delle directory sul filesystem montato. In pratica questo accade principalmente con i bind mount:
mount --bind /mnt/one/sub /mnt/partial
In /proc/mounts
, le voci per /mnt/one
e /mnt/partial
avere lo stesso dispositivo, lo stesso tipo di filesystem e le stesse opzioni. Le informazioni che /mnt/partial
mostra solo la parte del filesystem che è radicata in /sub
è visibile nelle informazioni del punto di montaggio per processo in /proc/$pid/mountinfo
(colonna 4). Le voci hanno questo aspetto:
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
Forse questo potrebbe fare al caso tuo:
findmnt | grep "\["
Esempio:
$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep "\["
│ └─/tmp/foo /dev/sda2[/media] ext4 rw,relatime,data=ordered
Il kernel non gestisce bind mount diversi dal normale monta dopo il fatto. L'unica differenza riguarda ciò che accade mentre mount
corre.
Quando monti un filesystem (ad es. con mount -t ext4 /dev/sda1 /mnt
) il kernel (un po' semplificato) esegue tre passaggi:
- Il kernel cerca un driver di filesystem per il tipo di filesystem specificato (se si omette
-t
o usa-t auto
mount
indovina il tipo per te e fornisce il tipo indovinato al kernel) - Il kernel istruisce il driver del filesystem per accedere al filesystem usando il percorso di origine e qualsiasi opzione fornita. A questo punto il filesystem è identificato solo da una coppia di numeri maggiore:minore.
- Il filesystem è associato a un percorso (il punto di montaggio). Il kernel utilizza anche alcune delle opzioni di montaggio qui. (
nodev
per esempio è un'opzione sul punto di montaggio, non sul filesystem. Puoi avere un bind mount connodev
e uno senza)
Se esegui un bind mount (es. con mount --bind /a /b
) accade quanto segue:
- Il kernel risolve quale filesystem contiene il percorso di origine e il percorso relativo dal punto di montaggio alla directory.
- Il filesystem è legato al nuovo punto di montaggio utilizzando 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:
- Il kernel risolve quale filesystem è responsabile della directory in cui deve essere creato il file.
- Viene creato un nuovo file nel filesystem. A questo punto il file ha solo un numero di inode.
- Il nuovo file è collegato a un nome file nella directory.
Se crei un hard link accade quanto segue:
- Il kernel risolve il numero di inode del file sorgente.
- Il file è collegato al nome del 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
Ma , poiché puoi identificare tutti i collegamenti fisici a un file confrontando i numeri di inode, puoi identificare tutti i montaggi su un filesystem confrontando i numeri major:minor dei montaggi.
Puoi farlo con findmnt -o TARGET,MAJ:MIN
o guardando direttamente /proc/self/mountinfo
(vedi la documentazione del kernel Linux per maggiori informazioni).
Il seguente script Python elenca tutti i bind mount. Presuppone che il punto di montaggio più vecchio con il percorso relativo più breve alla radice del file system montato sia il punto di montaggio 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))