在 bash 脚本中我有以下几行:
TARGETS="$(findmnt -n -v -t btrfs -o TARGET --list)"
UUIDS="$(findmnt -n -v -t btrfs -o UUID --list)"
我在一些服务器上运行这个脚本(运行 Arch Linux)。但是,它在 NFS 服务器上失败。在这种情况下,findmnt 返回多个挂载点对于给定的 UUID(由于 NFS 服务器上的绑定安装)。 A要求我的脚本的最终结果是我得到了一个列表每个 UUID 一个挂载点。
我在这里找到了一个非常好的答案(仅显示“有趣”的挂载点/过滤不感兴趣的类型)并尝试了那里讨论的所有建议,但我仍然无法消除 findmnt 返回给定 UUID 的多个安装点 - 即使问题缩小到仅由绑定安装引起的重复。 (我错过了什么?)
作为临时解决方法,我所做的是创建一个有限的选项卡文件,其中仅包含我想要显示的安装,然后我使用-F
findmnt 的选项。我的自定义选项卡文件是 fstab 的副本,其中删除了所有绑定安装。
TARGETS="$(findmnt -n -v -t btrfs -o TARGET --list -F /etc/fstab.custom)"
UUIDS="$(findmnt -n -v -t btrfs -o UUID --list -F /etc/fstab.custom)"
显然,这是一种脆弱的方法,一旦 /etc/fstab 中发生任何更改并且我的自定义选项卡文件未手动更新,该方法就会中断。 (我还必须手动删除一些导致自定义文件重复的非绑定安装,因此现阶段它绝对不是一个可靠的解决方案。)
有什么更好的方法可以达到预期的结果?我可以想象这可能可以使用 findmnt 过滤器来解决,也可以使用应用于 findmnt 返回的列表的外部过滤器来解决。
我所有的绑定安装都以“/srv/nfs/”开头。将这些从列表中过滤出来将是一个好的开始,尽管这也让我觉得这是一个有点脆弱的解决方案(因为有一天有人可能决定更改 NFS 绑定安装在服务器上的组织方式)。
另外,我不太擅长 bash 或 awk,不知道对 findmnt 返回的结果进行后处理的正确方法。我想了想:
findmnt -n -t btrfs -o UUID,TARGET --list | grep -v -E "/srv/nfs|.tapp|/var/log"
但这似乎与自定义选项卡文件一样脆弱,因为对路径名的任何更改都会破坏它。
findmnt -n -t btrfs -o UUID,TARGET --list
以下是我的系统之一返回的示例(简化了挂载点):
473c1g34-23ec-41dd-671f-c71473ad7d36 /
473c1g34-23ec-41dd-671f-c71473ad7d36 /srv/nfs/foo/wunder
473c1g34-23ec-41dd-671f-c71473ad7d36 /srv/nfs/foo/tinder
473c1g34-23ec-41dd-671f-c71473ad7d36 /.tapp
473c1g34-23ec-41dd-671f-c71473ad7d36 /var/log
473c1g34-23ec-41dd-671f-c71473ad7d36 /var/log/.tapp
13f4361e-771e-44b3-7413-a613bf4e331b /bar
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user1/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user6/Desktop
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user3/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user4/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user5/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user6/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /bar/.tapp
3ac663cc-e7e4-4764-7a7a-1d3fa16b376b /foo/files
3ac663cc-e7e4-4764-7a7a-1d3fa16b376b /srv/nfs/foo/files
4c61646e-1a1d-4d67-7d47-1446e41d6341 /bar/baz
4c61646e-1a1d-4d67-7d47-1446e41d6341 /srv/nfs/bar/baz/goop/stuff
4c61646e-1a1d-4d67-7d47-1446e41d6341 /srv/nfs/bar/baz/goop/widgets
4c61646e-1a1d-4d67-7d47-1446e41d6341 /srv/nfs/bar/baz/pie
4c61646e-1a1d-4d67-7d47-1446e41d6341 /srv/nfs/bar/baz/goop/gadgets
4c61646e-1a1d-4d67-7d47-1446e41d6341 /bar/baz/.tapp
我需要过滤掉所有 nfs 绑定挂载(以 /srv/nfs 开头的挂载)以及包含 /.tapp 的所有挂载点和 /var/log 的挂载点。有没有办法用 findmnt 选项来做到这一点?如果没有的话,如何在 bash 中做到这一点?
更新:为了保持问题的重点,我很高兴有一种方法可以从 findmnt 结果列表中排除绑定安装。为了提供答案,请随意忽略其他重复的安装点,例如 /var/log 创建的安装点。
更新2:这是 json 格式的 findmnt 输出的示例。我没有找到一种方法来区分绑定安装和我想要保留的输出中的绑定安装(/foo/files)。
{"target": "/srv/nfs/bar/user1/Documents", "uuid": "13f4361e-771e-44b3-7413-a613bf4e331b"},
{"target": "/srv/nfs/home/user5/Desktop", "uuid": "13f4361e-771e-44b3-7413-a613bf4e331b"},
{"target": "/srv/nfs/home/user3/Documents", "uuid": "13f4361e-771e-44b3-7413-a613bf4e331b"},
{"target": "/srv/nfs/home/user4/Documents", "uuid": "13f4361e-771e-44b3-7413-a613bf4e331b"},
{"target": "/foo/files", "uuid": "3ac663cc-e7e4-4764-7a7a-1d3fa16b376b"},
答案1
从仅列出绑定安装,看来bind挂载挂载后无法与原来区分。虽然部分绑定(其中挂载点的子目录在某处绑定挂载)确实在输出中显示不同findmnt
,但无法区分在其他地方绑定挂载的挂载点。
所以如果我这样做:
sudo mount -o bind / /srv
sudo mount -o bind /media /mnt
我无法区分/
和之间的/srv
安装信息,但我也许能够区分/media
和/mnt
。
因此,剩下的就是简单地从中删除重复的条目findmnt
:
findmnt -n -t btrfs -o UUID,TARGET -r | awk '!a[$1]++'
使用该-r
选项而不是-l
,它将转义输出中的特殊字符,以便您可以安全地处理路径:
$ findmnt -n -t ext4 -o UUID,TARGET -r
d4873b63-0956-42a7-9dcf-bd64e495a9ff /
..
d4873b63-0956-42a7-9dcf-bd64e495a9ff /srv/media
d4873b63-0956-42a7-9dcf-bd64e495a9ff /a\x20b
d4873b63-0956-42a7-9dcf-bd64e495a9ff /srv/a\x20b
在这里,a b
被转义为a\x20b
。您可以printf "%b"
在 bash 中使用来扩展转义字符:
$ findmnt -n -t ext4 -o UUID,TARGET -r | bash -c 'while read -r uuid point; do printf "%b\n" "$point"; done'
/
...
/srv/media
/srv/a b
/a b
/srv/a b