バインドマウントのみを一覧表示する


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が、いくつかの違いがあり、そのうちの1つはバインドマウントを追跡しません。

カーネルによって保持されているが、には表示されていない情報の1つ/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準拠です(Bourneでサポートされているかどうか忘れています)。事実を確認してください。Debian安定版(util-linux-ng 2.17.2からマウント)でマウントされたファイルシステム/etc/mtabbindオプションがあることを確認できますmount --bind /source /target
ジル 'SO-悪であるのをやめる

@Gilles混乱を取り除くために間違ったコメントを削除しました。あなたは正しい、それは確かにPOSIX準拠です。また、今、私たちは別の行動を見ている理由を理解mountして/etc/mtab。古いバージョンのutil-linux-ngがあるDebian安定版を使用しています。私はもはや同じ持っているようだしないことを新しいバージョンがあるDebianのテスト使用しています/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
どうやら、これはマウントポイントのサブディレクトリがバインドマウントされている場合にのみ機能します。場合は/、それ自体がバインドが装着され、例えば、出力はありません[...]
ムル

8

カーネルは、事後の通常のマウントとは異なるバインドマウントを処理しません。唯一の違いは、mount実行中に起こることです。

ファイルシステムを(たとえばwithでmount -t ext4 /dev/sda1 /mnt)マウントすると、カーネル(少し簡略化された)は3つのステップを実行します。

  1. カーネルは、指定されたファイルシステムタイプのファイルシステムドライバーを探します(省略-tまたは使用-t auto mountした場合、タイプが推測され、推測されたタイプがカーネルに提供されます)
  2. カーネルは、ソースパスと提供されたオプションを使用してファイルシステムにアクセスするようファイルシステムドライバーに指示します。この時点で、ファイルシステムはmajor:minor番号のペアでのみ識別されます。
  3. ファイルシステムはパス(マウントポイント)にバインドされています。カーネルは、ここでマウントオプションの一部も使用します。(nodevたとえば、ファイルシステムではなく、マウントポイントのオプションです。バインドマウントを使用する場合nodevと使用しない場合があります)

バインドマウント(withなどmount --bind /a /b)を実行すると、次のことが起こります。

  1. カーネルは、マウントポイントからディレクトリへのソースパスと相対パスを含むファイルシステムを解決します。
  2. ファイルシステムは、オプションと相対パスを使用して新しいマウントポイントにバインドされます。

mount --move質問に関係ないため、スキップします。)

これは、Linuxでのファイルの作成方法と非常に似ています。

  1. カーネルは、ファイルを作成するディレクトリを担当するファイルシステムを解決します。
  2. ファイルシステムに新しいファイルが作成されます。この時点で、ファイルにはiノード番号のみがあります。
  3. 新しいファイルは、ディレクトリ内のファイル名にリンクされます。

ハードリンクを作成すると、次のことが起こります。

  1. カーネルは、ソースファイルのiノード番号を解決します。
  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

ただし、iノード番号を比較することでファイルへのすべてのハードリンクを識別できるため、マウントのmajor:minor番号を比較することでファイルシステムへのすべてのマウントを識別することができます。

これを行う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」形式の行を削除します。

Debianストレッチでテスト済み。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.