Список лише прив’язувати кріплення


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, і я переглянув останні джерела, і ні в якому разі не бачу прив’язаної інформації, записаної в будь-якому місці, яка б дозволила вам отримати греп bind. З іншого боку, те, що я запропонував у своїй відповіді , насправді перераховує прив'язку створених --bind, а також використання bind опції .
aculich

@aculich сумісний з </etc/mtab awk …POSIX (я забуваю, чи підтримується він у Bourne). Будь ласка, перевірте свої факти. Я можу підтвердити, що /etc/mtabє bindможливість для файлової системи, встановленої mount --bind /source /targetна стабільному Debian (монтувати з util-linux-ng 2.17.2).
Жиль "ТАК - перестань бути злим"

@Gilles Я видалив свій помилковий коментар, щоб усунути плутанину. Ви маєте рацію, це дійсно сумісні з 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

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. Створюється новий файл у файловій системі. На даний момент у файлу є лише номер 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 --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" видаляє рядки формату "дерево".

Випробуваний на розтяжці Debian.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.