我在运行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应该先挂载/mypath,然后挂载/newplace和/mypath。
命令umount /newplace首先应该是umount /newplace,然后是也应该是 umount /mypath。
我可以更改/etc/fstab和设备的其他一些细节。但我不能更改调用mount /newplace的脚本。我也不能自动化/newplace,因为它通常需要保持未挂载,除非运行脚本。
我一直在阅读有关递归绑定挂载、共享、私有、从属和其他挂载选项的文章,但是我还没有看到实现我所寻求的东西的方法。
更新:作为对注释的响应,这显然不是递归挂载,所以我称之为“先决条件”挂载。我希望这个词是恰当的。我想到了“反向递归挂载”这个术语,但这似乎很糟糕。我认为“先决条件”指的是必须先来的东西,它为必要的东西提供了持续的基础。一般来说,前提条件不能被遗忘或移除,而必须继续这样做。
在这种情况下,/mypath (先决条件)和/newplace (必需)在安装/newplace时都保持挂载,在调用umount /newplace时它们都将被卸载(当然也可能是相反的顺序)。
理想的解决方案将使用systemd、Python 3或Xonsh。( Bash脚本也可以接受。我没有安装zsh或其他shell。)
发布于 2021-11-06 14:35:08
如果您确实希望在LABEL=XYZ上将FS的“主”子do安装在/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它在tmpdir中挂载整个FS,绑定-将子and挂载到目的地,然后卸载并移除tmpdir。
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语法相同(因此甚至应该在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,在/some/dir中添加一个执行相同操作的D26脚本:
#! /bin/sh -
if [ "$1" = /newplace ]; then
/bin/mount /mypath || exit
fi
exec /bin/mount "$@"并将您的脚本称为:
PATH="/some/dir:$PATH" your-script its argshttps://unix.stackexchange.com/questions/676413
复制相似问题