Como excluir montagens de ligações da lista de resultados do findmnt?

2

Em um script bash eu tenho as seguintes linhas:

TARGETS="$(findmnt -n -v -t btrfs -o TARGET --list)"
UUIDS="$(findmnt -n -v -t btrfs -o UUID --list)"

Eu executo este script em alguns servidores (executando o Arch Linux). No entanto, ele falha em servidores NFS. Nesse caso, o findmnt retorna vários pontos de montagem para um determinado UUID (devido a montagens de ligação nos servidores NFS). Um requisito do meu script é que acabo com uma lista de um ponto de montagem para cada UUID .

Encontrei uma resposta muito boa aqui ( Mostrando apenas pontos de montagem “interessantes” / filtrando tipos não interessantes ) e tentei todas as sugestões discutidas lá e ainda não consigo eliminar o findmnt de retornar vários pontos de montagem para um determinado UUID - mesmo quando o problema é reduzido a duplicatas causadas apenas por montagens de ligação. (Eu perdi alguma coisa?)

Como uma solução temporária, o que fiz foi criar um arquivo de guia limitado que contém apenas as montagens que quero que sejam exibidas e, em seguida, uso a opção -F com findmnt. Meu arquivo de guia personalizado é uma cópia do fstab com todas as montagens de ligação excluídas.

TARGETS="$(findmnt -n -v -t btrfs -o TARGET --list -F /etc/fstab.custom)"
UUIDS="$(findmnt -n -v -t btrfs -o UUID --list -F /etc/fstab.custom)"

Obviamente, essa é uma abordagem frágil que será interrompida assim que qualquer alteração em / etc / fstab e meu arquivo de guia personalizado não for atualizado manualmente. (Eu também tive que excluir manualmente alguns não-bind-montagens que causam duplicatas do meu arquivo personalizado, por isso definitivamente não é uma solução robusta nesta fase.)

Qual é a melhor maneira de alcançar o resultado desejado? Eu posso imaginar que isso pode ser resolvido com filtros findmnt ou pode ser resolvido com filtros externos aplicados à lista retornada por findmnt.

Todas as minhas montagens de bind começam com "/ srv / nfs /". Filtrar esses fora da lista seria um bom começo, embora isso também me pareça uma solução um tanto frágil (porque alguém pode decidir mudar como as montagens de ligação do NFS são organizadas no servidor um dia).

Também não sou bom o suficiente no bash ou no awk para saber o caminho certo para pós-processar os resultados retornados pelo findmnt. Eu pensei sobre isso:

findmnt -n -t btrfs -o UUID,TARGET --list | grep -v -E "/srv/nfs|.tapp|/var/log"

Mas isso parece tão frágil quanto o arquivo de guia personalizado, porque qualquer alteração nos nomes dos caminhos o quebrará.

Veja um exemplo do que é retornado por findmnt -n -t btrfs -o UUID,TARGET --list em um dos meus sistemas (pontos de montagem simplificados):

473c1g34-23ec-41dd-671f-c71473ad7d36 /
473c1g34-23ec-41dd-671f-c71473ad7d36 /srv/nfs/foo/wunder
473c1g34-23ec-41dd-671f-c71473ad7d36 /srv/nfs/foo/tinder
473c1g34-23ec-41dd-671f-c71473ad7d36 /.tapp
473c1g34-23ec-41dd-671f-c71473ad7d36 /var/log
473c1g34-23ec-41dd-671f-c71473ad7d36 /var/log/.tapp
13f4361e-771e-44b3-7413-a613bf4e331b /bar
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user1/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user6/Desktop
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user3/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user4/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user5/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /srv/nfs/bar/user6/Documents
13f4361e-771e-44b3-7413-a613bf4e331b /bar/.tapp
3ac663cc-e7e4-4764-7a7a-1d3fa16b376b /foo/files
3ac663cc-e7e4-4764-7a7a-1d3fa16b376b /srv/nfs/foo/files
4c61646e-1a1d-4d67-7d47-1446e41d6341 /bar/baz
4c61646e-1a1d-4d67-7d47-1446e41d6341 /srv/nfs/bar/baz/goop/stuff
4c61646e-1a1d-4d67-7d47-1446e41d6341 /srv/nfs/bar/baz/goop/widgets
4c61646e-1a1d-4d67-7d47-1446e41d6341 /srv/nfs/bar/baz/pie
4c61646e-1a1d-4d67-7d47-1446e41d6341 /srv/nfs/bar/baz/goop/gadgets
4c61646e-1a1d-4d67-7d47-1446e41d6341 /bar/baz/.tapp

Eu precisaria filtrar todas as montagens de ligação nfs (aquelas iniciando com / srv / nfs) e todos os pontos de montagem contendo /.tapp e o ponto de montagem para / var / log. Existe uma maneira de fazer isso com opções findmnt? Se não, como fazer isso no bash?

UPDATE : para manter a questão focada, eu ficaria feliz com uma maneira de excluir apenas as montagens de bind da lista de resultados do findmnt. Para fornecer uma resposta, sinta-se à vontade para ignorar os outros pontos de montagem duplicados, como os criados por / var / log.

UPDATE 2 : aqui está um exemplo da saída do findmnt no formato json. Eu não vejo uma maneira de distinguir as montagens de bind daquele na saída que eu gostaria de manter (/ foo / files).

{"target": "/srv/nfs/bar/user1/Documents", "uuid": "13f4361e-771e-44b3-7413-a613bf4e331b"},
{"target": "/srv/nfs/home/user5/Desktop", "uuid": "13f4361e-771e-44b3-7413-a613bf4e331b"},
{"target": "/srv/nfs/home/user3/Documents", "uuid": "13f4361e-771e-44b3-7413-a613bf4e331b"},
{"target": "/srv/nfs/home/user4/Documents", "uuid": "13f4361e-771e-44b3-7413-a613bf4e331b"},
{"target": "/foo/files", "uuid": "3ac663cc-e7e4-4764-7a7a-1d3fa16b376b"},
    
por MountainX 14.03.2018 / 01:32

1 resposta

2

De Listar somente montagens de bind , parece que as montagens de bind não podem ser distinguidas do original após a montagem. Embora ligações parciais (em que um subdiretório de um ponto de montagem é ligado em algum lugar) apareçam de forma diferente em findmnt output, não há como distinguir um ponto de montagem que foi montado em outro lugar.

Então, se eu fizesse:

sudo mount -o bind / /srv
sudo mount -o bind /media /mnt

Eu não seria capaz de distinguir entre / e /srv em termos de informações de montagem, mas talvez eu seja capaz de distinguir entre /media e /mnt .

Então, o que resta é simplesmente remover entradas duplicadas de findmnt :

findmnt -n -t btrfs -o UUID,TARGET -r | awk '!a[$1]++'

Use a opção -r em vez de -l , que escapará de caracteres especiais na saída para que você possa manipular caminhos com segurança:

$ findmnt -n -t ext4 -o UUID,TARGET -r
d4873b63-0956-42a7-9dcf-bd64e495a9ff /
..
d4873b63-0956-42a7-9dcf-bd64e495a9ff /srv/media
d4873b63-0956-42a7-9dcf-bd64e495a9ff /a\x20b
d4873b63-0956-42a7-9dcf-bd64e495a9ff /srv/a\x20b

Aqui, a b é salvo como a\x20b . Você pode usar printf "%b" no bash para expandir os caracteres de escape:

$ findmnt -n -t ext4 -o UUID,TARGET -r | bash -c 'while read -r uuid point; do printf "%b\n" "$point"; done'
/
...
/srv/media
/srv/a b
/a b
/srv/a b
    
por 14.03.2018 / 01:45