Список только привязывать крепления

24

Вместо использования mount | grepя хотел бы использовать mount -l -t bind, но это не работает, и -t noneпоказывает все крепления.

l0b0
источник

Ответы:

28

Bind mounts не является типом файловой системы или параметром смонтированной файловой системы; это параметры операции монтирования . Насколько я знаю, следующие последовательности команд приводят к практически одинаковым системным состояниям в отношении ядра:

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

Таким образом, единственный способ вспомнить, какие монтирования были bind mounts - это журнал 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
@ Жиль На самом деле, вы можете сделать это, просто используя, findmnt | fgrep [как описано здесь .
aculich
@Gilles Что mount --versionвы используете для записи какой-либо bindинформации /etc/mtab? Я использую версию 2.20.1, и я посмотрел последние версии источников, и ни в одном из случаев я не вижу информацию о привязке, записанную где-либо, что позволит вам использовать grep bind. С другой стороны, то, что я предложил в своем ответе , на самом деле включает в себя список привязок, созданных с --bindиспользованием bind опции .
aculich
@aculich </etc/mtab awk …является POSIX-совместимым (я забываю, поддерживается ли он в Bourne). Пожалуйста, проверьте ваши факты. Я могу подтвердить, что /etc/mtabимеет bindопцию для файловой системы, смонтированной mount --bind /source /targetв стабильной версии Debian (смонтировать из util-linux-ng 2.17.2).
Жиль "ТАК - перестань быть злым"
@ Жиль Я удалил свой ошибочный комментарий, чтобы избежать путаницы. Вы правы, это действительно POSIX-совместимый. Также теперь я понимаю причину, по которой мы видим различное поведение mountи /etc/mtab. Вы используете стабильную версию Debian, которая имеет более старую версию util-linux-ng; Я не буду с помощью тестирования 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
olopopo
источник
1
Очевидно, это работает только тогда, когда подкаталог точки монтирования монтируется с привязкой. /Например, если сам подключен, то у вывода нет [...].
Муру,
8

Ядро не обрабатывает привязку монтирования, отличную от обычной монтировки после факта. Разница лишь в том, что происходит во время mountпробежек.

Когда вы монтируете файловую систему (например, с помощью mount -t ext4 /dev/sda1 /mnt), ядро ​​(немного упрощенное) выполняет три шага:

  1. Ядро ищет драйвер файловой системы для указанного типа файловой системы (если вы пропустите -tили используете, -t auto mountугадывает тип для вас и предоставляет ядру предполагаемый тип)
  2. Ядро инструктирует драйвер файловой системы для доступа к файловой системе, используя исходный путь и любые предоставленные опции. На этом этапе файловая система идентифицируется только парой мажор: младший номер.
  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

Но , поскольку вы можете идентифицировать все жесткие ссылки на файл, сравнивая номера инодов, вы можете идентифицировать все монтирования в файловой системе, сравнивая основные: второстепенные номера монтирований.

Вы можете сделать это с помощью 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))
cg909
источник
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")
n3rdopolis
источник
0

Это похоже на другой ответ findmnt, но позволяет избежать проблемы форматирования.

Чтобы показать все субмонтирования:

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

Чтобы показать все субмонтирования файловых систем типа ext4:

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

Чтобы показать все монтирования, кроме субмаунтов:

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

Чтобы показать все монтирования файловых систем типа ext4, кроме submounts:

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

«-N» удаляет заголовки, а «--list» удаляет строки формата «дерево».

Протестировано на Debian Stretch.

sg23
источник