설치하려는 마운트 지점에 대한 필수 마운트 지점을 어떻게 자동으로 설치합니까?

설치하려는 마운트 지점에 대한 필수 마운트 지점을 어떻게 자동으로 설치합니까?

저는 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먼저 마운트를 해제 /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

관련 정보