Linux

如何從 findmnt 結果列表中排除綁定掛載?

  • March 14, 2018

在 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 伺服器上的綁定掛載)。我的腳本的一個要求是我最終得到每個 UUID 的一個掛載點的列表。

我在這裡找到了一個非常好的答案(僅顯示“有趣的”掛載點/過濾不感興趣的類型)並嘗試了那裡討論的所有建議,但我仍然無法消除 findmnt 為給定的 UUID 返回多個掛載點——即使問題是縮小到僅由綁定安裝引起的重複。(我錯過了什麼?)

作為臨時解決方法,我所做的是製作一個有限的選項卡文件,其中僅包含我想要顯示的掛載,然後我使用-Ffindmnt 選項。我的自定義選項卡文件是 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"},

List only bind mounts看來,綁定後的 mounts 似乎無法與原來的 mount 區分開來。雖然部分綁定(掛載點的子目錄綁定掛載在某處)在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

引用自:https://unix.stackexchange.com/questions/430074