바인드 마운트 만 나열


24

을 사용하는 대신을 사용 mount | grep하고 싶지만 mount -l -t bind작동하지 않으며 모든 마운트를 -t none보여줍니다 .

답변:


28

바인드 마운트는 파일 시스템 유형이 아니며 마운트 된 파일 시스템의 매개 변수도 아닙니다. 그것들은 마운트 작업의 매개 변수입니다 . 내가 아는 한 다음 명령 시퀀스는 커널에 관한 한 본질적으로 동일한 시스템 상태로 이어집니다.

mount /dev/foo /mnt/one; mount --bind /mnt/one /mnt/two
mount /dev/foo /mnt/two; mount --bind /mnt/two /mnt/one

따라서 어떤 마운트가 바인드 마운트인지 기억하는 유일한 방법은에 mount남아있는 명령 로그입니다 /etc/mtab. 바인드 마운트 조작은 bind마운트 옵션으로 표시됩니다 (이로 인해 파일 시스템 유형이 무시됩니다). 그러나 mount특정 옵션 세트로 마운트 된 파일 시스템 만 나열 할 수있는 옵션이 없습니다. 따라서 자체 필터링을 수행해야합니다.

mount | grep -E '[,(]bind[,)]'
</etc/mtab awk '$4 ~ /(^|,)bind(,|$)/'

참고 /etc/mtab가에 의해 유지되는 텍스트 파일 인 경우에 여기에만 유용합니다 mount. 일부 배포판 /etc/mtab/proc/mounts대신에 심볼릭 링크로 설정 됩니다. /proc/mounts대부분과 동일 /etc/mtab하지만 몇 가지 차이점이 있으며 그 중 하나는 바인드 마운트를 추적하지 않습니다.

커널에 의해 유지되지만로 표시되지 않은 정보 /proc/mounts는 마운트 지점이 마운트 된 파일 시스템에서 디렉토리 트리의 일부만 표시 할 때입니다. 실제로 이것은 대부분 바인드 마운트에서 발생합니다.

mount --bind /mnt/one/sub /mnt/partial

에서 /proc/mounts의에 대한 항목 /mnt/one/mnt/partial같은 장치, 같은 파일 시스템 유형과 같은 옵션이 있습니다. 그 정보 /mnt/partial를 루트있어 파일 시스템의 부분만을 도시 /sub에서 프로세스 당 마운트 포인트 정보에 볼 /proc/$pid/mountinfo(칼럼 4). 해당 항목은 다음과 같습니다.

12 34 56:78 / /mnt/one rw,relatime - ext3 /dev/foo rw,errors=remount-ro,data=ordered
12 34 56:78 /sub /mnt/partial rw,relatime - ext3 /dev/foo rw,errors=remount-ro,data=ordered

1
@Gilles 실제로, 여기에 설명 된findmnt | fgrep [ 대로 간단히 사용할 수 있습니다 .
aculich

@Gilles mount --version어떤 bind정보 를 기록 하고 /etc/mtab있습니까? 나는 2.20.1 버전을 사용하고 있으며 최신 소스를 보았고 어느 경우에도 grep 할 수있는 바인딩 정보가 기록되어 있지 않습니다 bind. 반면에, 내가 대답 에서 제안한 것은 실제로 옵션--bind 으로뿐만 아니라 생성 된 바인드 마운트를 나열 합니다 . bind
aculich

@ aculich </etc/mtab awk …는 POSIX 호환입니다 (본에서 지원되는지 여부는 잊어 버립니다). 사실을 확인하십시오. 나는 그 확인할 수 /etc/mtabbind파일 시스템이 장착에 대한 옵션 mount --bind /source /target데비안 안정에을 (폴더의 유틸리티 - 리눅스-ng를 2.17.2을에서 마운트).
Gilles 'SO- 악마 중지'

@Gilles 혼란을 제거하기 위해 잘못된 의견을 삭제했습니다. 맞습니다. 실제로 POSIX를 준수합니다. 또한 나는 우리가 mount와의 다른 행동을 보는 이유를 이해합니다 /etc/mtab. util-linux-ng의 이전 버전을 가진 데비안 안정을 사용하고 있습니다; 더 이상 동일한 /etc/mtab동작 을하지 않는 최신 버전의 데비안 테스트를 사용하고 있습니다. 왜냐하면 그의 배포가 최신 버전을 사용하고 있는지 @rozcietrzewiacz에서 보지 못했을 것 bind입니다 /etc/mtab.
aculich

1
@aculich findmnt답변으로 게시해야합니다 . 그런데 대상 디렉토리가 다른 마운트 지점이 아닌 경우에만 작동합니다. 예를 들어보십시오sudo mount --bind / foo && findmnt | grep foo
l0b0

21

아마도 이것은 트릭을 할 수 있습니다 :

findmnt | grep  "\["

예:

$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep  "\["
│ └─/tmp/foo                     /dev/sda2[/media] ext4            rw,relatime,data=ordered

1
분명히 이것은 마운트 포인트의 서브 디렉토리가 바인드 마운트 된 경우에만 작동합니다. /예를 들어, 자체가 바인드 마운트 된 경우 출력에가 없습니다 [...].
muru

8

커널은 사실 이후 일반 마운트 와 다른 바인드 마운트를 처리하지 않습니다 . mount달리는 동안 일어나는 일만 다릅니다 .

파일 시스템을 마운트 할 때 (예 :로 mount -t ext4 /dev/sda1 /mnt) 커널 (약간 단순화)은 세 단계를 수행합니다.

  1. 커널은 지정된 파일 시스템 유형에 대한 파일 시스템 드라이버를 찾습니다 (생략 -t하거나 사용 -t auto mount하는 경우 유형을 추측하여 추측 된 유형을 커널에 제공)
  2. 커널은 파일 시스템 드라이버가 소스 경로와 제공된 옵션을 사용하여 파일 시스템에 액세스하도록 지시합니다. 이 시점에서 파일 시스템은 major : minor 숫자 쌍으로 만 식별됩니다.
  3. 파일 시스템은 경로 (마운트 포인트)에 바인딩됩니다. 커널은 여기서 마운트 옵션 중 일부를 사용합니다. ( nodev예를 들어, 파일 시스템이 아닌 마운트 지점의 옵션입니다. 바인드 마운트를 사용 nodev하거나 사용하지 않고 마운트 할 수 있습니다 )

바인드 마운트 (예 :로 mount --bind /a /b)를 수행하면 다음이 발생합니다.

  1. 커널은 마운트 지점에서 디렉토리까지의 소스 경로와 상대 경로를 포함하는 파일 시스템을 확인합니다.
  2. 파일 시스템은 옵션과 상대 경로를 사용하여 새 마운트 지점에 바인딩됩니다.

( mount --move질문과 관련이 없기 때문에을 생략 하겠습니다.)

이것은 Linux에서 파일을 작성하는 방법과 매우 유사합니다.

  1. 커널은 파일을 작성해야하는 디렉토리를 담당하는 파일 시스템을 분석합니다.
  2. 파일 시스템에 새로운 파일이 생성됩니다. 이 시점에서 파일에는 inode 번호 만 있습니다.
  3. 새 파일은 디렉토리의 파일 이름에 연결됩니다.

하드 링크를 만들면 다음이 발생합니다.

  1. 커널은 소스 파일의 inode 번호를 확인합니다.
  2. 파일이 대상 파일 이름에 연결되어 있습니다.

보다시피 생성 된 파일과 하드 링크는 구분할 수 없습니다 :

$ touch first
$ ln first second
$ ls -li
1184243 -rw-rw-r-- 2 cg909 cg909 0 Feb 20 23:56 /tmp/first
1184243 -rw-rw-r-- 2 cg909 cg909 0 Feb 20 23:56 /tmp/second

그러나 inode 번호를 비교하여 파일에 대한 모든 하드 링크를 식별 할 수 있으므로 메이저 : 마운트의 마운트 수를 비교하여 파일 시스템에 대한 모든 마운트를 식별 할 수 있습니다.

findmnt -o TARGET,MAJ:MIN직접 또는 직접보고 이를 수행 할 수 있습니다 /proc/self/mountinfo( 자세한 내용은 Linux 커널 설명서 참조 ).

다음 Python 스크립트는 모든 바인드 마운트를 나열합니다. 마운트 된 파일 시스템의 루트에 대한 상대 경로가 가장 짧은 가장 오래된 마운트 지점이 원래 마운트 인 것으로 가정합니다.

#!/usr/bin/python3

import os.path, re
from collections import namedtuple

MountInfo = namedtuple('MountInfo', ['mountid', 'parentid', 'devid', 'root', 'mountpoint', 'mountoptions', 'extra', 'fstype', 'source', 'fsoptions'])

mounts = {}

def unescape(string):
    return re.sub(r'\\([0-7]{3})', (lambda m: chr(int(m.group(1), 8))), string)

with open('/proc/self/mountinfo', 'r') as f:
    for line in f:
        # Parse line
        mid, pid, devid, root, mp, mopt, *tail = line.rstrip().split(' ')
        extra = []
        for item in tail:
            if item != '-':
                extra.append(item)
            else:
                break
        fstype, src, fsopt = tail[len(extra)+1:]
        # Save mount info
        mount = MountInfo(int(mid), int(pid), devid, unescape(root), unescape(mp), mopt, extra, fstype, unescape(src), fsopt)
        mounts.setdefault(devid, []).append(mount)

for devid, mnts in mounts.items():
    # Skip single mounts
    if len(mnts) <= 1:
        continue
    # Sort list to get the first mount of the device's root dir (if still mounted)
    mnts.sort(key=lambda x: x.root)
    src, *binds = mnts
    # Print bind mounts
    for bindmount in binds:
        if src.root == bindmount.root:
            srcstring = src.mountpoint
        else:
            srcstring = src.mountpoint+':/'+os.path.relpath(bindmount.root, src.root)
        print('{0} -> {1.mountpoint} ({1.mountoptions})'.format(srcstring, bindmount))

0
unset DONE1FSES
FSES=$(findmnt -vUPno SOURCE,FSROOT,TARGET,MAJ:MIN)
FSES=${FSES//MAJ:MIN/MAJ_MIN}
while read SEARCH1FS
do
  unset DONE2FSES
  eval "$SEARCH1FS"
  SEARCH1SOURCE=$SOURCE
  SEARCH1FSROOT=$FSROOT
  SEARCH1TARGET=$TARGET
  SEARCH1MAJMIN=$MAJ_MIN

  FS1WASHANDLED=0
  while read DONE1FS 
  do
    if [[ $DONE1FS == $MAJ_MIN ]]
    then
      FS1WASHANDLED=1
      break
    fi
  done < <(echo "$DONE1FSES")


  if [[ ($SEARCH1FSROOT == /) && ($FS1WASHANDLED == 0) ]]
  then
  DONE1FSES+=$MAJ_MIN$'\n'
  while read SEARCH2FS
  do
    eval "$SEARCH2FS"
    SEARCH2SOURCE=$SOURCE
    SEARCH2FSROOT=$FSROOT
    SEARCH2TARGET=$TARGET
    SEARCH2MAJMIN=$MAJ_MIN

    FS2WASHANDLED=0
    while read DONE2FS 
    do
      if [[ $DONE2FS == $SEARCH2FS ]]
      then
        FS2WASHANDLED=1
        break
      fi
    done < <(echo "$DONE2FSES")

    if [[ ($SEARCH1MAJMIN == $SEARCH2MAJMIN)  && ($SEARCH1TARGET != $SEARCH2TARGET )  && ($FS2WASHANDLED == 0 ) ]]
    then
      DONE2FSES+=$SEARCH2FS$'\n'
      echo "$SEARCH1TARGET$SEARCH2FSROOT   --> $SEARCH2TARGET"
    fi

  done < <(echo "$FSES")


  fi
done   < <(echo "$FSES")

0

이것은 다른 findmnt 답변과 유사하지만 형식 문제를 피합니다.

모든 서브 마운트를 표시하려면

findmnt --kernel -n --list | grep '\['

ext4 유형의 파일 시스템의 모든 서브 마운트를 표시하려면 다음을 수행하십시오.

findmnt --kernel -t ext4 -n --list | grep '\['

서브 마운트를 제외한 모든 마운트를 표시하려면 :

findmnt --kernel -n --list | grep -v '\['

서브 마운트를 제외한 ext4 유형의 파일 시스템 마운트를 모두 표시하려면 다음을 수행하십시오.

findmnt --kernel -t ext4 -n --list | grep -v '\['

"-n"은 헤더를 제거하고 "--list"는 "tree"형식의 행을 제거합니다.

데비안 스트레치에서 테스트했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.