Listar apenas montagens de ligação

24

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

l0b0
fonte

Respostas:

28

Montagens de ligação não são do tipo sistema de arquivos nem 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 seqüências de comandos levam a estados de 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 em que montagens eram montagens de ligação é o log de mountcomandos restantes /etc/mtab. Uma operação de montagem de ligação é indicada pela opção debind montagem (que faz com que o tipo de sistema de arquivos seja ignorado). Mas não tem opção para listar apenas sistemas de arquivos montados com um conjunto específico de conjuntos de opções. Portanto, você precisa fazer sua própria filtragem.mount

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

Observe que /etc/mtabsó é útil aqui se for um arquivo de texto mantido por mount. Algumas distribuições são configuradas /etc/mtabcomo um link simbólico /proc/mounts; /proc/mountsé basicamente equivalente a, /etc/mtabmas possui algumas diferenças, uma das quais não está rastreando montagens de ligação.

Uma informação que é retida pelo kernel, mas não mostrada /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 ligação:

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

Em /proc/mounts, as entradas /mnt/onee /mnt/partialtêm o mesmo dispositivo, o mesmo tipo de sistema de arquivos e as mesmas opções. As informações que /mnt/partialmostram apenas a parte do sistema de arquivos enraizada /subsão visíveis nas informações do ponto de montagem por processo em /proc/$pid/mountinfo(coluna 4). As entradas 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
Gilles 'SO- parar de ser mau'
fonte
11
@Gilles Na verdade, você pode fazer isso simplesmente usando findmnt | fgrep [o explicado aqui .
Aculich
@Gilles O que mount --versionvocê está usando para registrar alguma bindinformação /etc/mtab? Estou usando a versão 2.20.1 e procurei as fontes mais recentes e, em nenhum dos casos, vejo as informações de ligação registradas em qualquer lugar que permitam que você aguarde bind. Por outro lado, o que sugeri na minha resposta , na verdade, lista montagens de ligação criadas com --bindo uso da bind opção .
aculich
@aculich </etc/mtab awk …é compatível com POSIX (eu esqueço se é suportado no Bourne). Por favor, verifique seus fatos. Eu posso confirmar que /etc/mtabtem a bindopção para um sistema de arquivos montado mount --bind /source /targetno Debian stable (monte a partir do util-linux-ng 2.17.2).
Gilles 'SO- deixa de ser mau'
@ Gilles Excluí meu comentário incorreto para remover a confusão. Você está certo, é realmente compatível com POSIX. Agora também entendo a razão pela qual estamos vendo comportamentos diferentes de mounte /etc/mtab. Você está usando o Debian stable, que possui a versão mais antiga do util-linux-ng; Eu estou usando testes Debian que tem uma versão mais recente que não parece ter o mesmo /etc/mtabcomportamento, o que é talvez por isso que @rozcietrzewiacz não viu bindem em /etc/mtabse sua distribuição também está usando uma versão mais recente?
Aculich # 6/12
11
@aculich Você deve postar findmntcomo resposta. Só funciona se o diretório de destino não for outro ponto de montagem, a propósito. Tente por exemplosudo mount --bind / foo && findmnt | grep foo
l0b0 19/11/2013
21

Talvez isso possa funcionar:

findmnt | grep  "\["

Exemplo:

$ mkdir /tmp/foo
$ sudo mount --bind /media/ /tmp/foo
$ findmnt | grep  "\["
│ └─/tmp/foo                     /dev/sda2[/media] ext4            rw,relatime,data=ordered
olopopo
fonte
11
Aparentemente, isso só funciona quando um subdiretório de um ponto de montagem é montado em ligação. Se /ele próprio estiver montado em ligação, por exemplo, a saída não possui a [...].
Muru
8

O kernel não suporta montagens de ligação diferentes das normais montagens após o fato. Os únicos diferem no que acontece durante a mountexecução.

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 um driver do sistema de arquivos para o tipo de sistema de arquivos especificado (se você omitir -tou usar-t auto mount adivinhar o tipo para você e fornecer o tipo de adivinhação ao 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 de números principais: secundários.
  3. O sistema de arquivos está vinculado a um caminho (o ponto de montagem). O kernel também usa algumas das opções de montagem aqui. ( nodevpor exemplo, é uma opção no ponto de montagem, não no sistema de arquivos. Você pode ter uma montagem de ligação com nodeve uma sem)

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

  1. O kernel resolve qual sistema de arquivos contém o caminho de origem e o caminho relativo do ponto de montagem ao diretório.
  2. O sistema de arquivos é vinculado 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 à maneira como os arquivos são criados no Linux:

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

Se você criar um link físico, acontece 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

Porém , como é possível identificar todos os hardlinks para um arquivo comparando os números de inode, você pode identificar todas as montagens em um sistema de arquivos comparando o principal: número menor de montagens.

Você pode fazer isso consultandofindmnt -o TARGET,MAJ:MIN diretamente /proc/self/mountinfo( consulte a documentação do kernel do Linux para obter mais informações). ).

O script Python a seguir lista todas as montagens de ligação. Ele pressupõe que o ponto de montagem mais antigo com o caminho relativo mais curto para a raiz do sistema de arquivos montado seja 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))
cg909
fonte
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
fonte
0

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

Para mostrar todos os submounts:

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

Para mostrar todos os submounts de sistemas de arquivos do tipo ext4:

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

Para mostrar todas as montagens, excluindo submounts:

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

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

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 Debian.

sg23
fonte