Listar apenas montagens de ligação

19

Em vez de usar mount | grep , gostaria de usar mount -l -t bind , mas isso não funciona e -t none mostra todas as montagens .

    
por l0b0 04.08.2011 / 15:35

5 respostas

26

As montagens de ligação não são um tipo de sistema de arquivos nem um parâmetro de um sistema de arquivos montado; eles são parâmetros de uma operação de montagem . Até onde eu sei, as seguintes sequências de comandos levam a estados do sistema essencialmente idênticos no que diz respeito ao kernel:

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

Portanto, a única maneira de lembrar quais montagens foram ligadas é o log dos comandos mount restantes em /etc/mtab . Uma operação de montagem de ligação é indicada pela opção bind mount (que faz com que o tipo de sistema de arquivos seja ignorado). Mas mount não tem opção de listar apenas sistemas de arquivos montados com um conjunto particular de conjuntos de opções. Portanto, você precisa fazer sua própria filtragem.

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

Observe que /etc/mtab só é útil aqui se for um arquivo de texto mantido por mount . Algumas distribuições configuram /etc/mtab como um link simbólico para /proc/mounts ; /proc/mounts é principalmente equivalente a /etc/mtab , mas tem algumas diferenças, uma das quais não acompanha as montagens de bind.

Uma informação retida pelo kernel, mas não mostrada em /proc/mounts , é quando um ponto de montagem mostra apenas uma parte da árvore de diretórios no sistema de arquivos montado. Na prática, isso acontece principalmente com montagens de bind:

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

Em /proc/mounts , as entradas para /mnt/one e /mnt/partial têm o mesmo dispositivo, o mesmo tipo de sistema de arquivos e as mesmas opções. As informações que /mnt/partial mostra apenas a parte do sistema de arquivos com raiz em /sub é visível nas informações de ponto de montagem por processo em /proc/$pid/mountinfo (coluna 4). As entradas lá são assim:

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
    
por 04.08.2011 / 18:45
16

Talvez isso possa fazer o truque:

findmnt | grep  "\["

Exemplo:

$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep  "\["
│ └─/tmp/foo                     /dev/sda2[/media] ext4            rw,relatime,data=ordered
    
por 17.06.2016 / 18:59
4

O kernel não suporta montagens de ligações diferentes das montagens normal após o fato. A única diferença é o que acontece enquanto mount é executado.

Quando você monta um sistema de arquivos (por exemplo, com mount -t ext4 /dev/sda1 /mnt ), o kernel (um pouco simplificado) executa três etapas:

  1. O kernel procura por um driver de sistema de arquivos para o tipo de sistema de arquivos especificado (se você omitir -t ou usar -t auto mount adivinha o tipo para você e fornecer o tipo adivinhado para o kernel)
  2. O kernel instrui o driver do sistema de arquivos a acessar o sistema de arquivos usando o caminho de origem e quaisquer opções fornecidas. Neste ponto, o sistema de arquivos é identificado apenas por um par major: minor number.
  3. O sistema de arquivos está ligado a um caminho (o ponto de montagem). O kernel também usa algumas das opções de montagem aqui. ( nodev , por exemplo, é uma opção no ponto de montagem, não no sistema de arquivos. Você pode ter uma montagem de ligação com nodev e outra sem)

Se você realizar uma montagem de ligação (por exemplo, com mount --bind /a /b ), ocorrerá o seguinte:

  1. O kernel resolve qual sistema de arquivos contém o caminho de origem e o caminho relativo do ponto de montagem para o diretório.
  2. O sistema de arquivos é ligado ao novo ponto de montagem usando as opções e o caminho relativo.

(Eu vou pular mount --move , porque não é relevante para a pergunta.)

Isso é semelhante a como os arquivos são criados no Linux:

  1. O kernel resolve qual sistema de arquivos é responsável pelo diretório no qual o arquivo deve ser criado.
  2. Um novo arquivo no sistema de arquivos é criado. Neste ponto, o arquivo tem apenas um número de inode.
  3. O novo arquivo está vinculado a um nome de arquivo no diretório.

Se você fizer um link físico, acontecerá o seguinte:

  1. O kernel resolve o número de inode do arquivo de origem.
  2. O arquivo está vinculado ao nome do arquivo de destino.

Como você pode ver, o arquivo criado e o link físico são indistinguíveis:

$ 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

Mas , como você pode identificar todos os hardlinks para um arquivo comparando os números de inode, é possível identificar todas as montagens em um sistema de arquivos comparando os principais: números menores de montagens.

Você pode fazer isso com findmnt -o TARGET,MAJ:MIN ou diretamente em /proc/self/mountinfo ( veja o kernel do Linux documentação para mais informações ).

O seguinte script Python lista todas as montagens de ligação. Ele assume que o ponto de montagem mais antigo com o caminho relativo mais curto para a raiz do sistema de arquivos montado é a montagem original.

#!/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))
    
por 21.02.2017 / 01:22
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")
    
por 09.12.2016 / 02:24
0

Isso é semelhante à outra resposta do findmnt, mas evita o problema de formatação.

Para mostrar todas as submontagens:

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

Para mostrar todas as sub-montagens de sistemas de arquivos do tipo ext4:

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

Para mostrar todas as montagens, exceto submontagens:

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

Para mostrar todas as montagens de sistemas de arquivos do tipo ext4, excluindo submontagens:

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

O "-n" remove os cabeçalhos e o "--list" remove as linhas do formato "árvore".

Testado no trecho do Debian.

    
por 10.03.2018 / 16:33