Lista tylko łączy wierzchowce

24

Zamiast używać mount | grep, chciałbym użyć mount -l -t bind, ale to nie działa i -t nonepokazuje wszystkie wierzchowce.

l0b0
źródło

Odpowiedzi:

28

Montowania powiązań nie są typem systemu plików ani parametrem podłączonego systemu plików; są parametrami operacji montowania . O ile mi wiadomo, następujące sekwencje poleceń prowadzą do zasadniczo identycznych stanów systemu, jeśli chodzi o jądro:

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

Jedynym sposobem, aby zapamiętać, które wierzchowce były łączeniem wierzchowców, jest dziennik pozostałych mountpoleceń /etc/mtab. Operacja podłączenia powiązania jest wskazywana przez opcjębind podłączenia (która powoduje, że typ systemu plików jest ignorowany). Ale nie ma opcji, aby wyświetlić listę tylko systemów plików zamontowanych z określonym zestawem opcji. Dlatego musisz wykonać własne filtrowanie.mount

mount | grep -E '[,(]bind[,)]'
</etc/mtab awk '$4 ~ /(^|,)bind(,|$)/'

Pamiętaj, że /etc/mtabprzydaje się to tylko wtedy, gdy jest to plik tekstowy obsługiwany przez mount. Niektóre dystrybucje skonfigurowane /etc/mtabjako dowiązanie symboliczne /proc/mounts; /proc/mountsjest w większości równoważny, /etc/mtabale ma kilka różnic, z których jedna nie śledzi montowań powiązań.

Jedną z informacji, które są zatrzymywane przez jądro, ale nie są pokazywane w /proc/mounts, jest to, gdy punkt podłączenia pokazuje tylko część drzewa katalogów w zamontowanym systemie plików. W praktyce dzieje się tak głównie z oprawami bind:

mount --bind /mnt/one/sub /mnt/partial

W /proc/mounts, wpisy dla /mnt/onei /mnt/partialmają to samo urządzenie, ten sam typ systemu plików i te same opcje. Informacje, które /mnt/partialpokazują tylko tę część systemu plików, która jest zrootowana, /subsą widoczne w informacjach o punkcie montowania na proces w /proc/$pid/mountinfo(kolumna 4). Wpisy wyglądają tak:

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
Gilles „SO- przestań być zły”
źródło
1
@Gilles Właściwie można to zrobić używając zwyczajnie findmnt | fgrep [jak wyjaśniono tutaj .
aculich
@Gilles W jakim celu mount --versionwykorzystujesz te bindinformacje /etc/mtab? Korzystam z wersji 2.20.1 i sprawdziłem najnowsze źródła i w żadnym przypadku nie widzę zapisanych informacji o powiązaniach, które pozwoliłyby na grep bind. Z drugiej strony, to, co zasugerowałem w mojej odpowiedzi , faktycznie wyświetla listę opraw montowanych utworzonych za pomocą, --bindjak również przy użyciu bind opcji .
aculich
@aculich </etc/mtab awk …jest zgodny z POSIX (nie pamiętam, czy jest obsługiwany w Bourne). Sprawdź swoje fakty. Mogę potwierdzić, że /etc/mtabma bindopcję dla systemu plików zamontowanego mount --bind /source /targetna stabilnej wersji Debiana (mount z util-linux-ng 2.17.2).
Gilles „SO- przestań być zły”
@Gilles Usunąłem mój błędny komentarz, aby usunąć zamieszanie. Masz rację, to jest rzeczywiście zgodne z POSIX. Teraz też rozumiem powód, dla którego widzimy różne zachowania mounti /etc/mtab. Używasz stabilnej wersji Debiana, która ma starszą wersję util-linux-ng; Używam testów Debiana, który ma nowszą wersję, która nie wydaje się mieć ten sam /etc/mtabproblem, co jest być może dlatego @rozcietrzewiacz nie widzi bindw w /etc/mtabrazie jego dystrybucja jest również za pomocą nowszej wersji?
aculich
1
@aculich Powinieneś opublikować findmntjako odpowiedź. Nawiasem mówiąc, działa to tylko wtedy, gdy katalog docelowy nie jest innym punktem montowania. Spróbuj na przykładsudo mount --bind / foo && findmnt | grep foo
10b0
21

Może to załatwi sprawę:

findmnt | grep  "\["

Przykład:

$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep  "\["
│ └─/tmp/foo                     /dev/sda2[/media] ext4            rw,relatime,data=ordered
olopopo
źródło
1
Najwyraźniej działa to tylko wtedy, gdy zamontowany jest podkatalog punktu montowania. /Na przykład, jeśli samo jest zamontowane na wiązaniu, dane wyjściowe nie mają wartości [...].
muru
8

Jądro po fakcie nie obsługuje mocowań łączenia innych niż normalne . Jedyne różnią się tym, co dzieje się podczas mounturuchamiania.

Kiedy montujesz system plików (np. Z mount -t ext4 /dev/sda1 /mnt), jądro (nieco uproszczone) wykonuje trzy kroki:

  1. Jądro szuka sterownika systemu plików dla określonego typu systemu plików (jeśli pominiesz -tlub użyjesz -t auto mountzgaduje typ dla ciebie i dostarcza zgadnięty typ do jądra)
  2. Jądro instruuje sterownik systemu plików, aby uzyskał dostęp do systemu plików przy użyciu ścieżki źródłowej i dowolnych podanych opcji. W tym momencie system plików jest identyfikowany tylko przez parę głównych: mniejszych liczb.
  3. System plików jest powiązany ze ścieżką (punkt montowania). Jądro korzysta również z niektórych opcji montowania tutaj. ( nodevna przykład jest opcją w punkcie montowania, a nie w systemie plików. Możesz mieć podłączenie montowania z nodevjednym bez niego)

Jeśli wykonasz podłączenie wiązania (np. Za pomocą mount --bind /a /b), dzieje się tak:

  1. Jądro rozpoznaje, który system plików zawiera ścieżkę źródłową i ścieżkę względną od punktu montowania do katalogu.
  2. System plików jest powiązany z nowym punktem montowania za pomocą opcji i ścieżki względnej.

(Pominę mount --move, bo to nie dotyczy pytania).

Jest to dość podobne do sposobu tworzenia plików w systemie Linux:

  1. Jądro określa, który system plików jest odpowiedzialny za katalog, w którym plik powinien zostać utworzony.
  2. Zostanie utworzony nowy plik w systemie plików. W tym momencie plik ma tylko numer i-węzła.
  3. Nowy plik jest powiązany z nazwą pliku w katalogu.

Jeśli zrobisz twardy link, dzieje się tak:

  1. Jądro rozwiązuje numer i-węzła pliku źródłowego.
  2. Plik jest powiązany z docelową nazwą pliku.

Jak widać, utworzony plik i twardy link są nierozróżnialne:

$ 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

Ale ponieważ można zidentyfikować wszystkie dowiązania twarde do pliku, porównując numery i-węzłów, można zidentyfikować wszystkie podłączenia do systemu plików, porównując główne: mniejsze liczby podłączeń.

Możesz to zrobić findmnt -o TARGET,MAJ:MINbezpośrednio lub bezpośrednio /proc/self/mountinfo( patrz dokumentacja jądra Linux, aby uzyskać więcej informacji ).

Poniższy skrypt Pythona zawiera listę wszystkich podłączeń powiązań. Zakłada się, że najstarszym punktem podłączenia z najkrótszą ścieżką względną do katalogu głównego podłączonego systemu plików jest oryginalne podłączenie.

#!/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
źródło
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
źródło
0

Jest to podobne do innej odpowiedzi findmnt, ale pozwala uniknąć problemu z formatowaniem.

Aby wyświetlić wszystkie submounty:

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

Aby wyświetlić wszystkie podzbiory systemów plików typu ext4:

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

Aby wyświetlić wszystkie wierzchowce z wyłączeniem podrzędnych:

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

Aby wyświetlić wszystkie podłączenia systemów plików typu ext4 z wyłączeniem podliczeń:

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

„-N” usuwa nagłówki, a „--list” usuwa wiersze formatu „drzewa”.

Testowane na odcinku Debian.

sg23
źródło