在Linux中检测绑定挂载

6

我正在寻找一种方法来确定给定的路径是否是绑定挂载点(在Linux上)。检测常规挂载点的标准技术似乎并不起作用。即使mountpoint命令也无法检测绑定挂载点。


我真的很想了解你为什么会问这样的问题的原因。 - Basile Starynkevitch
它最初只是我认为自己需要的东西,现在它已经发展成更像是“我必须知道”的东西了。最初的原因是我正在编写一个相当全面的文件系统遍历器/扫描器。 - Shamless
然后你尝试记住已经访问过的i节点。 - Basile Starynkevitch
4个回答

6

我不确定是否有一种方法可以实现这个(除非可能是通过/etc/mtab/etc/fstab),因为我了解绑定挂载在挂载空间中有点像“硬链接”,而在文件层次结构中没有办法(一旦绑定挂载发生)区分源和目标挂载点。

你为什么要问这个?在我看来,绑定挂载主要用于从应用程序的角度隐藏这些内容(否则,您将使用符号链接进行目录操作-甚至在极少数情况下也可以使用硬链接)

而且,我刚刚通过您的问题发现的mountpoint似乎能够看到某些东西:

% grep /home /etc/fstab
UUID=000008-0003-000c-9ecd-0f1a /home           ext3    defaults        0       2
% grep /usr/src /etc/fstab
/home/Src /usr/src none bind 0 0
% mountpoint /usr/src
/usr/src is a mountpoint
% mountpoint /home/Src
/home/Src is not a mountpoint

通过使用 stracemountpoint 进行跟踪,我发现它正在对类似于 /usr/src/usr/src/.. 的目录进行 lstatstatfstat 系统调用。


(2016年11月添加:)

另请参见 /proc/mounts,例如:proc(5)nftw(3)


4
我认为 mountpoint 使用的技巧是查找 l/stat 路径和路径/..,然后查找不同设备 ID 或相同 inode。至于 fstat 调用,我不太确定,但它可能与挂载点检查无直接关联。至于“为什么”。你提出了一个很好的观点,我已经决定将相同设备中的链接挂载视为常规目录。话虽如此,我仍然很想知道如何检测它们。 目前我找到的最佳技术是扫描 /proc/mounts 和 /etc/mtab 获取信息。 - Shamless

2
你可以通过检查路径的设备ID和其父级的设备ID来判断一个路径是否是挂载点(前提是挂载的文件系统与父目录的文件系统不同 - 我从未尝试过将一个目录绑定到自身!)。
以下是一个快速的命令行演示:
$ cut -d ' ' -f2 /proc/mounts | xargs stat -c '%d %n'
18 /sys
4 /proc
6 /dev
19 /dev/pts
20 /run
2049 /
7 /sys/kernel/security
21 /dev/shm
22 /run/lock
23 /sys/fs/cgroup
24 /sys/fs/cgroup/unified
25 /sys/fs/cgroup/systemd
26 /sys/fs/pstore
27 /sys/fs/cgroup/perf_event
28 /sys/fs/cgroup/cpu,cpuacct
29 /sys/fs/cgroup/pids
30 /sys/fs/cgroup/blkio
31 /sys/fs/cgroup/memory
32 /sys/fs/cgroup/cpuset
33 /sys/fs/cgroup/net_cls,net_prio
34 /sys/fs/cgroup/devices
35 /sys/fs/cgroup/freezer
39 /proc/sys/fs/binfmt_misc
17 /dev/mqueue
8 /sys/kernel/debug
37 /dev/hugepages
2066 /home
39 /proc/sys/fs/binfmt_misc
44 /run/user/1000
45 /sys/fs/fuse/connections
2049 /run/schroot/mount/my-chroot-cb43935e-0812-45ea-af4f-965a1e2de91d
4 /run/schroot/mount/my-chroot-cb43935e-0812-45ea-af4f-965a1e2de91d/proc
18 /run/schroot/mount/my-chroot-cb43935e-0812-45ea-af4f-965a1e2de91d/sys
6 /run/schroot/mount/my-chroot-cb43935e-0812-45ea-af4f-965a1e2de91d/dev
19 /run/schroot/mount/my-chroot-cb43935e-0812-45ea-af4f-965a1e2de91d/dev/pts
2066 /run/schroot/mount/my-chroot-cb43935e-0812-45ea-af4f-965a1e2de91d/home
2049 /run/schroot/mount/my-chroot-cb43935e-0812-45ea-af4f-965a1e2de91d/tmp

一旦你知道它是一个挂载点,那么如果它的设备ID在/proc/mounts中有多个条目中都出现,你可以假设其中一个是绑定挂载。但是,找出哪个是绑定挂载,哪个是被绑定的仍然是这个答案中缺失的部分。
注意:/proc/mounts中的条目对于一些有问题的字符使用了八进制转义,因此一个强大的脚本需要通过printf %b或类似方法来处理这些字符。

stat 中,为什么要列出 inode 号码而不是设备号码? - Steve Piner
@Steve - 呃,因为我没有仔细阅读手册,没有看到我需要-f参数。我是个笨蛋。 - Toby Speight
我已经修好了。 - Toby Speight

1

findmnt 显示绑定挂载:

$ grep /opt /home /etc/fstab
/home/admin/opt  /opt  none bind 0
LABEL=raidhome /home ext4 defaults,nodiratime,relatime 0       2

$ findmnt --fstab /opt
TARGET SOURCE          FSTYPE OPTIONS
/opt   /home/admin/opt none   bind


$ findmnt /opt
TARGET SOURCE               FSTYPE OPTIONS
/opt   /dev/md1[/admin/opt] ext4   rw,nodiratime,relatime,stripe=16

$ findmnt -J /opt
{
   "filesystems": [
      {
         "target": "/opt",
         "source": "/dev/md1[/admin/opt]",
         "fstype": "ext4",
         "options": "rw,nodiratime,relatime,stripe=16"
      }
   ]
}

虽然不是十分直接,但信息都在那里。


-4
$ mount | grep bind

我不是很清楚你想要什么,这个命令符合你的需求吗?


2
“mount” 命令输出在现代系统(2022)中无法识别绑定挂载。 - jimav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接