如何為我正在掛載的掛載點自動掛載一個先決條件掛載點?
我正在執行 Arch Linux 和 systemd。
在
/etc/fstab
我有這樣的事情:LABEL=XYZ /mypath vfat noauto,[...] /mypath/main /newplace none bind,noauto 0 0
我目前必須
/newplace
使用兩個命令進行掛載:mount /mypath mount /newplace
我也必須
umount
兩者兼而有之。我需要將其簡化為一個
mount
(或umount
)命令:mount /newplace
由於現有腳本,我需要使用上面顯示的確切
mount
(和相關)命令。umount
澄清:單個命令
mount /newplace
應首先 mount/mypath
,然後 mount/newplace
並/mypath
應保持已安裝狀態。該命令
umount /newplace
應首先 umount/newplace
,然後也是umount/mypath
。我可以更改
/etc/fstab
設備的其他一些細節。但我無法更改呼叫mount /newplace
. 我也無法自動掛載/newplace
,因為它通常需要保持解除安裝狀態,除非在腳本執行時。我一直在閱讀有關遞歸綁定掛載、共享、私有、從屬和其他掛載選項的資訊,但我還沒有看到實現我所尋求的方法。
更新:回應評論,這顯然不是遞歸掛載,所以我稱之為“先決條件”掛載。我希望這個詞是合適的。我想到了“反向遞歸安裝”這個詞,但這似乎很糟糕。我認為“先決條件”是指必須先於並為必要條件提供持續基礎的東西。通常,在繼續進行必備項時,不能忘記或刪除必備項。
在這種情況下,
/mypath
(prerequisite) 和/newplace
(requisite) 在掛載時都保持掛載/newplace
,並且在呼叫時它們都將被掛載(當然可能以相反的順序)umount /newplace
。理想的解決方案將使用 systemd、Python 3 或 Xonsh。(也可以接受 Bash 腳本。我沒有安裝 zsh 或其他 shell。)
如果您確實希望將 FS 的“主”子目錄
LABEL=XYZ
安裝在 上/newplace
,而不特別需要將整個 FS 安裝在 上/mypath
,則可以添加如下行:LABEL=XYZ /newplace subdir subdir=main,srctype=vfat,noauto,... 0 0
並將
/sbin/mount.subdir
幫助程序(由 呼叫mount /newplace
,而不是直接呼叫)創建為如下腳本:#! /bin/zsh -p (( EUID == 0 )) || exec sudo -- "$0" "$@" PATH=/bin:/sbin:/usr/bin:/usr/sbin # mount -t subdir -o subdir=foo -o otheroption source /dest calls us # as mount.subdir source /dest -o rw,subdir=foo,otheroption dev=${1?} dest=${2?} opts=( ${(s[,])4?} ) # extract mandatory subdir option (( i = $opts[(I)subdir=*] )) || exit subdir=${opts[i]#*=} opts[i]=() # extract optional srctype option if (( i = $opts[(I)srctype=*] )); then type=(-t "$opts[i]") opts[i]=() else type=() fi tmpdir=$(mktemp -d) || exit mounted()true if mount "$type[@]" -o "${(j[,])opts}" -- "$dev" "$tmpdir" then mount --bind -- "$tmpdir/$subdir" "$dest" || mounted()false umount -- "$tmpdir" fi && rmdir -- "$tmpdir" && mounted
它將整個 FS 掛載在 tmpdir 中,將子目錄綁定掛載到目標,然後解除安裝並刪除 tmpdir。
如果,正如您在以後的編輯中所闡明的那樣,您確實希望同時安裝 和
/newplace
,而不僅僅是將 FS 的子目錄安裝在 中的最終目標的一些中間步驟,您可以採取類似的方法,這變得更容易了您只需要幫助器來安裝先決條件 FS(s):/mypath``/mypath``/myplace
LABEL=XYZ /mypath vfat noauto,[...] /myplace/main /newplace prereq prereq=/myplace,noauto,... 0 0
並將幫助程序創建
/sbin/mount.prereq
為腳本,例如:#! /bin/zsh -p (( EUID == 0 )) || exec sudo -- "$0" "$@" PATH=/bin:/sbin:/usr/bin:/usr/sbin src=${1?} dst=${2?} opts=( ${(s[,])4?} ) # extract prereq options for prereq in ${(M)opts:#prereq=*}; do prereq=${prereq#*=} mountpoint -q -- $prereq || mount -- $prereq || exit done opts=(${opts:#prereq=*}) exec mount --bind -o "${(j[,])opts}" -- "$src" "$dst"
請注意,
/mypath
解除安裝後不會自動/newplace
解除安裝。與 POSIX shell 語法相同(甚至應該在 中工作
bash
)可能看起來像:#! /bin/sh - [ "$(id -u)" -eq 0 ] || exec sudo -- "$0" "$@" PATH=/bin:/sbin:/usr/bin:/usr/sbin src="${1?}" dst="${2?}" set -o noglob IFS=, set -- ${4?} # extract prereq options for opt do case $opt in (prereq=*) prereq=${opt#*=} mountpoint -q -- "$prereq" || mount -- "$prereq" || exit ;; (*) set -- "$@" "$opt" esac shift done opts="$*" exec mount --bind -o "$opts" -- "$src" "$dst"
(未經測試)。
如果你不能編輯你的腳本,你可能會檢測它。例如,如果它寫在 中
bash
,則將其稱為:bash -c ' mount() { if [[ $1 = "/newplace" ]]; then command mount /mypath || return fi command mount "$@" } export -f mount exec "$0" "$@"' your-script its args
或者,如果它寫在 中
zsh
,添加到~/.zshenv
(或為該腳本/some/dir/.zshenv
設置):ZDOTDIR=/some/dir
if [[ $ZSH_SCRIPT:P = /path/to/your-script ]]; then mount() { if [[ $1 = /newplace ]]; then command mount /mypath || return fi command mount "$@" } fi
或者對於任何 shell,添加一個執行相同操作的
mount
腳本/some/dir
:#! /bin/sh - if [ "$1" = /newplace ]; then /bin/mount /mypath || exit fi exec /bin/mount "$@"
並將您的腳本稱為:
PATH="/some/dir:$PATH" your-script its args