インストールするマウントポイントに必要なマウントポイントをどのように自動的にインストールしますか?

インストールするマウントポイントに必要なマウントポイントをどのように自動的にインストールしますか?

私はArch Linuxとsystemdを実行しています。

私は/etc/fstab次のようなものがあります:

LABEL=XYZ       /mypath       vfat    noauto,[...]
/mypath/main    /newplace     none    bind,noauto    0 0

/newplace現在インストールするには、2つのコマンドを使用する必要があります。

mount /mypath
mount /newplace

私も両方umountになるはずです。

mountこれを1つの(またはumount)コマンドに減らす必要があります。

mount /newplace

既存のスクリプトのため、上記の正確なmount(および関連する)コマンドを使用する必要があります。umount言う:

単一のコマンドは、mount /newplace最初にマウント/mypathされ/newplace/mypath次にマウントされマウントされた状態を維持する必要があります。

このコマンドはumount /newplace最初にマウントを解除してから/newplaceマウントを解除する必要があります。返品削除/mypath

/etc/fstabマイデバイスの他の詳細を変更できます。ただし、呼び出されたスクリプトを変更することはできませんmount /newplace。また、/newplaceスクリプトが実行されない限り、通常はアンマウント状態を維持する必要があるため、自動マウントすることはできません。

再帰バインドマウント、共有、個人、スレーブ、およびその他のマウントオプションについて読みましたが、目的を達成する方法が見つかりませんでした。

アップデート:コメントによると、これは明らかに再帰マウントではないので、「前提条件」マウントと呼びます。その言葉が合うことを願っています。 「逆再帰のインストール」という言葉を考えていたのですが、良くないようです。私は「前提条件」を最初に行う必要があり、必要な条件に対する持続的な基盤を提供することだと思います。通常、前提条件の実行中に前提条件を忘れたり削除したりすることはできません。

この場合、/mypath(予防)と/newplace(必須)の両方がインストール時にインストールされたままになり、呼び出し/newplace時に両方が削除されます(もちろん逆の順序でもかまいません)umount /newplace

理想的な解決策は、systemd、Python 3、またはXonshを使用することです。 (Bashスクリプトも許可されています。zshや他のシェルはインストールされていません。)

答え1

具体的には、FS 全体ではなく FS の「home」サブディレクトリLABEL=XYZを にマウントする場合は、次の行を追加できます。/newplace/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をマウントしたいという最終目標に向かう中間ステップではなく、同様のアプローチをとることができます。必要なファイルシステムをマウントするヘルパープログラム:/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シェルと同じ構文(それでも動作するはずです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

または、すべてのシェルに対して同じ操作を実行するスクリプトを追加します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

関連情報