Bind mounts nejsou typem souborového systému, ani parametrem připojeného souborového systému; jsou to parametry operace připojení . Pokud vím, následující sekvence příkazů vedou k v podstatě identickým stavům systému, pokud jde o jádro:
mount /dev/foo /mnt/one; mount --bind /mnt/one /mnt/two
mount /dev/foo /mnt/two; mount --bind /mnt/two /mnt/one
Jediným způsobem, jak si zapamatovat, která připojení byla připojením vazby, je protokol mount
příkazy vlevo v /etc/mtab
. Operace připojení připojení je označena bind
připojit možnost (což způsobí, že typ souborového systému bude ignorován). Ale mount
nemá možnost vypsat pouze souborové systémy připojené s konkrétní sadou sad voleb. Proto musíte provést vlastní filtrování.
mount | grep -E '[,(]bind[,)]'
</etc/mtab awk '$4 ~ /(^|,)bind(,|$)/'
Všimněte si, že /etc/mtab
je zde užitečné pouze v případě, že se jedná o textový soubor spravovaný mount
. Některé distribuce nastavují /etc/mtab
jako symbolický odkaz na /proc/mounts
namísto; /proc/mounts
je většinou ekvivalentní /etc/mtab
ale má několik rozdílů, jedním z nich není sledování připojení připojení.
Jedna část informace, která je uchovávána jádrem, ale není zobrazena v /proc/mounts
, je, když bod připojení zobrazuje pouze část stromu adresářů na připojeném souborovém systému. V praxi se to většinou děje s připojeními typu bind:
mount --bind /mnt/one/sub /mnt/partial
V /proc/mounts
, záznamy pro /mnt/one
a /mnt/partial
mít stejné zařízení, stejný typ souborového systému a stejné možnosti. Informace, která /mnt/partial
zobrazuje pouze část souborového systému, která je zakořeněna na /sub
je viditelný v informacích o bodu připojení pro jednotlivé procesy v /proc/$pid/mountinfo
(sloupec 4). Záznamy tam vypadají takto:
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
Možná by to mohlo stačit:
findmnt | grep "\["
Příklad:
$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep "\["
│ └─/tmp/foo /dev/sda2[/media] ext4 rw,relatime,data=ordered
Jádro nezpracovává připojení připojení odlišná od normálního nasedne po faktu. Liší se pouze tím, co se stane při mount
běží.
Když připojíte souborový systém (např. s mount -t ext4 /dev/sda1 /mnt
) jádro (trochu zjednodušeně) provede tři kroky:
- Jádro hledá ovladač souborového systému pro zadaný typ souborového systému (pokud vynecháte
-t
nebo použijte-t auto
mount
uhodne typ za vás a poskytne uhodnutý typ jádru) - Jádro dává ovladači souborového systému pokyn k přístupu k souborovému systému pomocí cesty ke zdroji a všech poskytnutých možností. V tomto okamžiku je souborový systém identifikován pouze dvojicí major:minor number.
- Souborový systém je vázán na cestu (přípojný bod). Jádro zde také používá některé možnosti připojení. (
nodev
například je volba na přípojném bodu, nikoli na souborovém systému. Můžete mít připojení k připojení snodev
a jeden bez)
Pokud provedete připojení k připojení (např. s mount --bind /a /b
) stane se následující:
- Jádro řeší, který souborový systém obsahuje zdrojovou cestu a relativní cestu od bodu připojení k adresáři.
- Souborový systém je svázán s novým bodem připojení pomocí voleb a relativní cesty.
(Přeskočím mount --move
, protože to není pro otázku relevantní.)
Je to velmi podobné tomu, jak se soubory vytvářejí v systému Linux:
- Jádro řeší, který souborový systém je zodpovědný za adresář, ve kterém by měl být soubor vytvořen.
- Vytvoří se nový soubor v systému souborů. V tomto okamžiku má soubor pouze číslo inodu.
- Nový soubor je propojen s názvem souboru v adresáři.
Pokud vytvoříte pevný odkaz, stane se následující:
- Jádro rozlišuje číslo inodu zdrojového souboru.
- Soubor je propojen s cílovým názvem souboru.
Jak vidíte, vytvořený soubor a pevný odkaz jsou k nerozeznání:
$ 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
Ale , protože můžete identifikovat všechny pevné odkazy na soubor porovnáním čísel inodů, můžete identifikovat všechna připojení k souborovému systému porovnáním major:minor počtu připojení.
Můžete to udělat pomocí findmnt -o TARGET,MAJ:MIN
nebo přímým pohledem na /proc/self/mountinfo
(další informace naleznete v dokumentaci k jádru Linuxu).
Následující skript Pythonu uvádí všechna připojení připojení. Předpokládá, že nejstarší bod připojení s nejkratší relativní cestou ke kořenu připojeného souborového systému je původní připojení.
#!/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))