回答:
バインドマウントは、ファイルシステムタイプではなく、マウントされたファイルシステムのパラメーターでもありません。それらはマウント操作のパラメータです。私の知る限り、次の一連のコマンドは、カーネルに関する限り、本質的に同一のシステム状態をもたらします。
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
</etc/mtab awk …
はPOSIX準拠です(Bourneでサポートされているかどうか忘れています)。事実を確認してください。Debian安定版(util-linux-ng 2.17.2からマウント)でマウントされたファイルシステム/etc/mtab
のbind
オプションがあることを確認できますmount --bind /source /target
。
mount
して/etc/mtab
。古いバージョンのutil-linux-ngがあるDebian安定版を使用しています。私はもはや同じ持っているようだしないことを新しいバージョンがあるDebianのテスト使用しています/etc/mtab
@rozcietrzewiaczは見なかった理由かもしれないです行動を、bind
中に/etc/mtab
彼の分布も新しいバージョンを使用している場合は?
findmnt
回答として投稿してください。ちなみに、ターゲットディレクトリが別のマウントポイントでない場合にのみ機能します。たとえば、sudo mount --bind / foo && findmnt | grep foo
カーネルは、事後の通常のマウントとは異なるバインドマウントを処理しません。唯一の違いは、mount
実行中に起こることです。
ファイルシステムを(たとえばwithでmount -t ext4 /dev/sda1 /mnt
)マウントすると、カーネル(少し簡略化された)は3つのステップを実行します。
-t
または使用-t auto
mount
した場合、タイプが推測され、推測されたタイプがカーネルに提供されます)nodev
たとえば、ファイルシステムではなく、マウントポイントのオプションです。バインドマウントを使用する場合nodev
と使用しない場合があります)バインドマウント(withなどmount --bind /a /b
)を実行すると、次のことが起こります。
(mount --move
質問に関係ないため、スキップします。)
これは、Linuxでのファイルの作成方法と非常に似ています。
ハードリンクを作成すると、次のことが起こります。
ご覧のとおり、作成されたファイルとハードリンクは区別できません。
$ 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))
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")
これは他の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ストレッチでテスト済み。
findmnt | fgrep [
いるように、これを簡単に使用できます。