Listar os arquivos acessados ​​por um programa

64

time é um comando brilhante se você quiser descobrir quanto tempo de CPU um determinado comando leva.

Estou procurando algo semelhante que possa listar os arquivos que estão sendo acessados ​​por um programa e seus filhos. Em tempo real ou como um relatório depois.

Atualmente eu uso:

#!/bin/bash

strace -ff -e trace=file "$@" 2>&1 | perl -ne 's/^[^"]+"(([^\\"]|\\[\\"nt])*)".*/$1/ && print'

mas falhará se o comando a executar envolver sudo. Não é muito inteligente (seria bom se pudesse listar apenas os arquivos existentes ou com problemas de permissão ou agrupá-los em arquivos lidos e escritos). Também straceé lento, por isso seria bom com uma escolha mais rápida.

Ole Tange
fonte
Dado o seu uso strace, presumo que você esteja especificamente interessado no Linux. Corrigir?
Gilles 'SO- stop be evil' (
Linux é minha principal preocupação.
precisa saber é o seguinte

Respostas:

51

Desisti e codifiquei minha própria ferramenta. Para citar seus documentos:

SYNOPSIS
    tracefile [-adefnu] command
    tracefile [-adefnu] -p pid

OPTIONS
    -a        List all files
    -d        List only dirs
    -e        List only existing files
    -f        List only files
    -n        List only non-existing files
    -p pid    Trace process id
    -u        List only files once

Ele gera apenas os arquivos, assim você não precisa lidar com a saída de strace.

https://gitlab.com/ole.tange/tangetools/tree/master/tracefile

Ole Tange
fonte
obrigado! a saída do strace é absolutamente ilegível. Eu não sei onde encontrar os documentos - seria bom se tivesse uma opção de ajuda -h / -. Eu também aprecio uma opção que mostra apenas edições de arquivos, não acessos.
Xerus
@Xerus Clone gitlab.com/ole.tange/tangetools e execute make && sudo make install. Então você pode correr man tracefile.
31818 Ole Tange
4
Boa ferramenta. Empacotado, para instalar: yum -y install https://extras.getpagespeed.com/release-el7-latest.rpmeyum -y install tracefile
Danila Vershinin
27

Você pode rastrear as chamadas do sistema strace, mas há realmente uma penalidade de velocidade inevitável. Você precisa executar stracecomo root se o comando for executado com privilégios elevados:

sudo strace -f -o foo.trace su user -c 'mycommand'

Outro método que é provável que seja mais rápido é para pré-carregar uma biblioteca que envolve funções de acesso do sistema de arquivos: LD_PRELOAD=/path/to/libmywrapper.so mycommand. A LD_PRELOADvariável de ambiente não será passada para programas invocados com privilégios elevados. Você precisaria escrever o código dessa biblioteca de invólucros ( aqui está um exemplo de "Construindo interpositores de bibliotecas para diversão e lucro" ); Não sei se há código reutilizável disponível na web.

Se você estiver monitorando os arquivos em uma hierarquia de diretórios específica, poderá fazer uma visualização do sistema de arquivos com o LoggedFS , de forma que todos os acessos através dessa visualização sejam registrados.

loggedfs -c my-loggedfs.xml /logged-view
mycommand /logged-view/somedir

Para configurar o LoggedFS, inicie com a configuração de amostra fornecida com o programa e leia a sintaxe do arquivo de configuração do LoggedFS .

Outra possibilidade é o subsistema de auditoria do Linux . Verifique se o auditddaemon foi iniciado e, em seguida, configure com o qual deseja fazer logon auditctl. Cada operação registrada é registrada em /var/log/audit/audit.log(em distribuições típicas). Para começar a assistir um arquivo específico:

auditctl -a exit,always -w /path/to/file

Se você colocar uma observação em um diretório, os arquivos nele e seus subdiretórios recursivamente também serão observados. Tome cuidado para não observar o diretório que contém os logs de auditoria. Você pode restringir o log a certos processos, consulte a auditctlpágina do manual para os filtros disponíveis. Você precisa ser root para usar o sistema de auditoria.

Gilles 'SO- parar de ser mau'
fonte
LD_PRELOADtambém não funcionará em binários estáticos.
David
6

Eu acho que você quer lsof (possivelmente canalizado para um grep no programa e em crianças). Ele informará todos os arquivos que estão sendo acessados ​​no momento no sistema de arquivos. Para obter informações sobre quais arquivos acessados ​​por processo ( daqui ):

lsof -n -p `pidof your_app`
tiojamil
fonte
11
Mas isso só me dá um instantâneo. O que eu preciso é quais arquivos ele tentou acessar. Pense na situação em que um programa se recusa a iniciar porque diz "Arquivo ausente". Como faço para descobrir qual arquivo ele estava procurando?
precisa saber é o seguinte
2

Eu tentei isso tracefile. Para mim, deu muito menos resultados que os meus strace ... | sed ... | sort -u. Eu até adicionei -s256a strace(1)linha de comando, mas não ajudou muito ...

Então eu tentei isso loggedfs. Primeiro, ele falhou, pois não tinha acesso de leitura / gravação ao diretório que tentei fazer logon. Depois de fazer o chmod 755 temporariamente, recebi alguns hits ...

Mas, para mim, fazer o seguinte parece funcionar melhor:

inotifywait -m -r -e OPEN /path/to/traced/directory

E depois processe a saída após executar o processo de seu interesse.

Isso não captura o acesso externo ao processo de arquivos do diretório rastreado, nem sabe se algum outro processo acessou a mesma árvore de diretórios, mas em muitos casos isso é uma ferramenta boa o suficiente para fazer o trabalho.

EDIT: inotifywait não captura o acesso de link simbólico (apenas os destinos após a resolução dos links simbólicos). Fui atingido por isso quando arquivei bibliotecas acessadas por um programa para uso futuro. Utilizamos alguns hackers perl glob extras para selecionar os links simbólicos nas bibliotecas notificadas para concluir o trabalho nesse caso específico.

EDIT2: pelo menos quando inotifying arquivos e os próprios links simbólicos de linha de comando inotifywait (por exemplo, inotifywait -m file symlinkou inotifywait symlink file) saída mostrará o acesso a qual é o primeiro na linha de comando (independentemente de qual, filede symlinkfor acessado). O inotifywait não suporta IN_DONT_FOLLOW - que, quando tentei programaticamente, apenas faz com que se veja acesso file(o que pode ou não ser o que se espera ...) independentemente da ordem na linha de comando

Tomi Ollila
fonte
"Para mim, deu muito menos correspondências do que as minhas" Você pode compartilhar um exemplo de tracefilefalta de acesso a um arquivo?
Ole Tange
Não sei ao certo o que você está perguntando exatamente:) ... Se eu tentar procurar arquivos dentro de / path / to / trace / directory / vejo OPEN no inotify output ... MAS stat (1) nos arquivos que pareço para obter resultados nos poucos casos que tentei (pergunto-me por que, há algum cache ocultando o conteúdo do diretório lendo da vista)
Tomi Ollila
Estou comentando o post do fanotify abaixo (tenho apenas 21 reputação, apesar de ter respondido por mais de uma década; exigir 50 para comentar sempre foi um obstáculo para mim ...) - o fanotify é uma coisa boa, mas não pode contornar a questão da desreferência de link simbólico (ou seja, no caso de links simbólicos, o arquivo final acessado é encontrado através da leitura de / proc / self / fd / <fd> .. de qualquer maneira +1: ing a resposta: D
Tomi Ollila
1

Embora possa não lhe dar controle suficiente (ainda?) Eu escrevi um programa que, pelo menos parcialmente, atende às suas necessidades, usando o fanotify e o desshare do linux-kernel para monitorar apenas arquivos modificados (ou lidos) por um processo específico e seus filhos . Comparado ao strace, é bastante rápido (;

Pode ser encontrado em https://github.com/tycho-kirchner/shournal

Exemplo no shell:

$ shournal -e sh -c 'echo hi > foo1; echo hi2 > foo2'
$ shournal -q --history 1
  # ...
  Written file(s):                                                                                                                                                                              
 /tmp/foo1 (3 bytes) Hash: 15349503233279147316                                                                                                                                             
 /tmp/foo2 (4 bytes) Hash: 2770363686119514911    
desovar
fonte