仅列出绑定安装


24

而不是使用mount | grep,我想使用mount -l -t bind,但这不起作用,并-t none显示所有坐骑。

Answers:


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/mtabbind挂载选项指示绑定挂载操作(这会导致文件系统类型被忽略)。但是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 2012年

@Gilles mount --version您正在使用什么记录任何bind信息/etc/mtab?我使用的是2.20.1版本,我查看了最新的资源,在任何情况下都没有看到绑定信息记录在任何可以让您使用grep的地方bind。另一方面,我在答案中提出的建议实际上列出了使用--bind以及使用bind option创建的绑定装架。
aculich 2012年

@aculich </etc/mtab awk …是POSIX兼容的(我忘记了Bourne是否支持它)。请检查您的事实。我可以确认在Debian稳定版上具有用于挂载文件系统/etc/mtabbind选项mount --bind /source /target(从util-linux-ng 2.17.2挂载)。
吉尔斯(Gillles)“所以-别再邪恶了”

@Gilles我删除了错误的评论,以消除混乱。没错,它确实符合POSIX。现在我也明白了我们看到mount和的行为不同的原因/etc/mtab。您正在使用的Debian稳定版具有较旧的util-linux-ng版本;我正在使用Debian测试,它的新版本似乎不再具有相同的/etc/mtab行为,这也许就是为什么@rozcietrzewiacz bind/etc/mtab他的发行版中是否也使用了新版本?
aculich 2012年

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运行时会发生什么。

当您挂载文件系统(例如使用mount -t ext4 /dev/sda1 /mnt)时,内核(稍微简化了)执行三个步骤:

  1. 内核会为指定的文件系统类型查找文件系统驱动程序(如果您省略-t或使用-t auto mount猜测类型,并向内核提供猜测的类型)
  2. 内核指示文件系统驱动程序使用源路径和任何提供的选项来访问文件系统。此时,该文件系统仅由一个main:minor数字对标识。
  3. 文件系统绑定到路径(挂载点)。内核在这里也使用了一些挂载选项。(nodev例如,是安装点上的一个选项,而不是文件系统上的一个选项。您可以使用一个绑定挂载nodev和一个不使用绑定挂载)

如果执行绑定安装(例如,使用mount --bind /a /b),则会发生以下情况:

  1. 内核解析哪个文件系统包含源路径以及从安装点到目录的相对路径。
  2. 使用选项和相对路径将文件系统绑定到新的安装点。

(我将跳过mount --move,因为它与问题无关。)

这与在Linux上创建文件的方式非常相似:

  1. 内核解析哪个文件系统负责应在其中创建文件的目录。
  2. 在文件系统中创建一个新文件。此时,文件只有一个索引节点号。
  3. 新文件链接到目录中的文件名。

如果进行硬链接,则会发生以下情况:

  1. 内核解析源文件的索引节点号。
  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编号来标识到文件的所有硬链接,因此可以通过比较main: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拉伸测试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.