Mount

如何為我正在掛載的掛載點自動掛載一個先決條件掛載點?

  • November 12, 2021

我正在執行 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

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