Bind-Mounts sind weder ein Dateisystemtyp noch ein Parameter eines gemounteten Dateisystems; sie sind Parameter einer Mount-Operation . Meines Wissens nach führen folgende Befehlsfolgen zu im Wesentlichen identischen Systemzuständen, soweit es den Kernel betrifft:
mount /dev/foo /mnt/one; mount --bind /mnt/one /mnt/two
mount /dev/foo /mnt/two; mount --bind /mnt/two /mnt/one
Die einzige Möglichkeit, sich daran zu erinnern, welche Mounts Bind-Mounts waren, ist das Protokoll von mount
Befehle verbleiben in /etc/mtab
. Ein Bind-Mount-Vorgang wird durch bind
angezeigt mount Option (was dazu führt, dass der Dateisystemtyp ignoriert wird). Aber mount
hat keine Option, nur Dateisysteme aufzulisten, die mit einem bestimmten Optionssatz gemountet wurden. Daher müssen Sie Ihre eigene Filterung vornehmen.
mount | grep -E '[,(]bind[,)]'
</etc/mtab awk '$4 ~ /(^|,)bind(,|$)/'
Beachten Sie, dass /etc/mtab
ist hier nur nützlich, wenn es sich um eine Textdatei handelt, die von mount
verwaltet wird . Einige Distributionen richten /etc/mtab
ein als symbolischer Link zu /proc/mounts
stattdessen; /proc/mounts
entspricht meistens /etc/mtab
hat aber ein paar Unterschiede, von denen einer darin besteht, Bindungshalterungen nicht zu verfolgen.
Eine Information, die vom Kernel gespeichert, aber nicht in /proc/mounts
angezeigt wird , wenn ein Einhängepunkt nur einen Teil des Verzeichnisbaums auf dem eingehängten Dateisystem anzeigt. In der Praxis geschieht dies meistens mit Bind Mounts:
mount --bind /mnt/one/sub /mnt/partial
Unter /proc/mounts
, die Einträge für /mnt/one
und /mnt/partial
dasselbe Gerät, denselben Dateisystemtyp und dieselben Optionen haben. Die Informationen, die /mnt/partial
zeigt nur den Teil des Dateisystems, der bei /sub
gerootet ist ist in den Mountpunktinformationen pro Prozess in /proc/$pid/mountinfo
sichtbar (Spalte 4). Einträge dort sehen so aus:
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
Vielleicht könnte dies den Zweck erfüllen:
findmnt | grep "\["
Beispiel:
$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep "\["
│ └─/tmp/foo /dev/sda2[/media] ext4 rw,relatime,data=ordered
Der Kernel handhabt Bind-Mounts nicht anders als normal steigt nachträglich auf. Sie unterscheiden sich nur darin, was während mount
passiert läuft.
Beim Mounten eines Dateisystems (zB mit mount -t ext4 /dev/sda1 /mnt
) führt der Kernel (etwas vereinfacht) drei Schritte aus:
- Der Kernel sucht nach einem Dateisystemtreiber für den angegebenen Dateisystemtyp (wenn Sie
-t
weglassen oder verwenden Sie-t auto
mount
errät den Typ für Sie und liefert den erratenen Typ an den Kernel) - Der Kernel weist den Dateisystemtreiber an, auf das Dateisystem unter Verwendung des Quellpfads und aller bereitgestellten Optionen zuzugreifen. An dieser Stelle wird das Dateisystem nur durch ein Major:Minor-Zahlenpaar identifiziert.
- Das Dateisystem ist an einen Pfad (den Einhängepunkt) gebunden. Auch hier verwendet der Kernel einige der Mount-Optionen. (
nodev
zum Beispiel ist eine Option auf dem Einhängepunkt, nicht auf dem Dateisystem. Mitnodev
können Sie ein Bindungsmount haben und eine ohne)
Wenn Sie einen Bind-Mount durchführen (z. B. mit mount --bind /a /b
) Folgendes passiert:
- Der Kernel löst auf, welches Dateisystem den Quellpfad und den relativen Pfad vom Einhängepunkt zum Verzeichnis enthält.
- Das Dateisystem wird mit den Optionen und dem relativen Pfad an den neuen Einhängepunkt gebunden.
(Ich überspringe mount --move
, weil es für die Frage nicht relevant ist.)
Das ist ganz ähnlich wie Dateien unter Linux erstellt werden:
- Der Kernel entscheidet, welches Dateisystem für das Verzeichnis zuständig ist, in dem die Datei erstellt werden soll.
- Eine neue Datei im Dateisystem wird erstellt. An dieser Stelle hat die Datei nur eine Inode-Nummer.
- Die neue Datei wird mit einem Dateinamen im Verzeichnis verknüpft.
Wenn Sie einen festen Link erstellen, passiert Folgendes:
- Der Kernel löst die Inode-Nummer der Quelldatei auf.
- Die Datei ist mit dem Zieldateinamen verknüpft.
Wie Sie sehen können, sind die erstellte Datei und der Hardlink nicht zu unterscheiden:
$ 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
Aber , da Sie alle Hardlinks zu einer Datei identifizieren können, indem Sie die Inode-Nummern vergleichen, können Sie alle Mounts zu einem Dateisystem identifizieren, indem Sie die Major:Minor-Nummern von Mounts vergleichen.
Sie können dies mit findmnt -o TARGET,MAJ:MIN
tun oder indem Sie direkt auf /proc/self/mountinfo
schauen (Weitere Informationen finden Sie in der Linux-Kernel-Dokumentation).
Das folgende Python-Skript listet alle Bind-Mounts auf. Es geht davon aus, dass der älteste Einhängepunkt mit dem kürzesten relativen Pfad zur Wurzel des eingehängten Dateisystems der ursprüngliche Einhängepunkt ist.
#!/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))