Answers:
绑定挂载既不是文件系统类型,也不是已挂载文件系统的参数。它们是安装操作的参数。据我所知,就内核而言,以下命令序列导致基本相同的系统状态:
mount /dev/foo /mnt/one; mount --bind /mnt/one /mnt/two
mount /dev/foo /mnt/two; mount --bind /mnt/two /mnt/one
因此,记住什么挂载是绑定挂载的唯一方法是mount
留下的命令日志/etc/mtab
。bind
挂载选项指示绑定挂载操作(这会导致文件系统类型被忽略)。但是mount
没有选项仅列出安装有一组特定选项集的文件系统。因此,您需要自己进行过滤。
mount | grep -E '[,(]bind[,)]'
</etc/mtab awk '$4 ~ /(^|,)bind(,|$)/'
请注意,/etc/mtab
仅在以下情况下才有用:mount
。某些发行版设置/etc/mtab
为与之的符号链接/proc/mounts
;/proc/mounts
几乎等效,/etc/mtab
但有一些区别,其中之一不是跟踪绑定安装。
内核保留但未显示的一条信息 /proc/mounts
显示的一条信息是安装点仅显示已安装文件系统上目录树的一部分时。实际上,这主要发生在绑定安装中:
mount --bind /mnt/one/sub /mnt/partial
在/proc/mounts
,对于条目/mnt/one
和/mnt/partial
具有相同的设备,相同的文件系统类型和相同的选项。该信息/mnt/partial
只能说明真实扎根在文件系统的一部分/sub
是可见的每个进程的安装点信息/proc/$pid/mountinfo
(第4栏)。那里的条目看起来像这样:
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
mount --version
您正在使用什么记录任何bind
信息/etc/mtab
?我使用的是2.20.1版本,我查看了最新的资源,在任何情况下都没有看到绑定信息记录在任何可以让您使用grep的地方bind
。另一方面,我在答案中提出的建议实际上列出了使用--bind
以及使用bind
option创建的绑定装架。
</etc/mtab awk …
是POSIX兼容的(我忘记了Bourne是否支持它)。请检查您的事实。我可以确认在Debian稳定版上具有用于挂载文件系统/etc/mtab
的bind
选项mount --bind /source /target
(从util-linux-ng 2.17.2挂载)。
mount
和的行为不同的原因/etc/mtab
。您正在使用的Debian稳定版具有较旧的util-linux-ng版本;我正在使用Debian测试,它的新版本似乎不再具有相同的/etc/mtab
行为,这也许就是为什么@rozcietrzewiacz bind
在/etc/mtab
他的发行版中是否也使用了新版本?
findmnt
作为答案。顺便说一下,它仅在目标目录不是另一个安装点时才有效。尝试例如sudo mount --bind / foo && findmnt | grep foo
事实发生之后,内核不会处理与普通安装不同的绑定安装。唯一的区别是mount
运行时会发生什么。
当您挂载文件系统(例如使用mount -t ext4 /dev/sda1 /mnt
)时,内核(稍微简化了)执行三个步骤:
-t
或使用-t auto
mount
猜测类型,并向内核提供猜测的类型)nodev
例如,是安装点上的一个选项,而不是文件系统上的一个选项。您可以使用一个绑定挂载nodev
和一个不使用绑定挂载)如果执行绑定安装(例如,使用mount --bind /a /b
),则会发生以下情况:
(我将跳过mount --move
,因为它与问题无关。)
这与在Linux上创建文件的方式非常相似:
如果进行硬链接,则会发生以下情况:
如您所见,创建的文件和硬链接是无法区分的:
$ 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
但是,由于您可以通过比较inode编号来标识到文件的所有硬链接,因此可以通过比较main:minor挂载号来标识到文件系统的所有挂载。
您可以通过findmnt -o TARGET,MAJ:MIN
或直接查看来完成此操作/proc/self/mountinfo
(有关更多信息,请参见Linux内核文档。)。
以下Python脚本列出了所有绑定安装。假定到已安装文件系统根目录的相对路径最短的最旧的安装点是原始安装。
#!/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))
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")
这类似于其他findmnt答案,但是避免了格式问题。
要显示所有子安装:
findmnt --kernel -n --list | grep '\['
要显示ext4类型的文件系统的所有子装载:
findmnt --kernel -t ext4 -n --list | grep '\['
要显示所有安装,不包括子安装:
findmnt --kernel -n --list | grep -v '\['
要显示ext4类型的文件系统的所有装载(不包括子装载):
findmnt --kernel -t ext4 -n --list | grep -v '\['
“ -n”删除标题,而“ --list”删除“ tree”格式的行。
经过Debian拉伸测试。
findmnt | fgrep [
按照此处的说明进行操作。