it-swarm.it

Elenca i file a cui accede un programma

time è un comando brillante se vuoi capire quanto tempo CPU impiega un dato comando.

Sto cercando qualcosa di simile che possa elencare i file a cui accede un programma e i suoi figli. O in tempo reale o come rapporto successivo.

Attualmente uso:

#!/bin/bash

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

ma fallisce se il comando da eseguire coinvolge Sudo. Non è molto intelligente (sarebbe bello se potesse elencare solo i file esistenti o che presentavano problemi di autorizzazione o raggrupparli in file letti e file scritti). Anche strace è lento, quindi sarebbe una scelta più veloce.

65
Ole Tange

Ho rinunciato e codificato il mio strumento. Per citare dai suoi documenti:

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

Emette solo i file, quindi non è necessario gestire l'output di strace.

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

56
Ole Tange

Puoi rintracciare le chiamate di sistema con strace, ma c'è davvero un'inevitabile penalità di velocità. È necessario eseguire strace come root se il comando viene eseguito con privilegi elevati:

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

Un altro metodo che potrebbe essere più veloce è precaricare una libreria che avvolge le funzioni di accesso al filesystem: LD_PRELOAD=/path/to/libmywrapper.so mycommand. Il LD_PRELOAD La variabile di ambiente non verrà passata ai programmi richiamati con privilegi elevati. Dovresti scrivere il codice di quella libreria wrapper ( ecco un esempio da "Costruire interposer di librerie per divertimento e profitto" ); Non so se ci sono codici riutilizzabili disponibili sul web.

Se stai monitorando i file in una particolare gerarchia di directory, puoi fare una vista del filesystem con LoggedFS in modo tale che tutti gli accessi attraverso quella vista siano registrati.

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

Per configurare LoggedFS, iniziare con la configurazione di esempio fornita con il programma e leggere Sintassi del file di configurazione di LoggedFS .

Un'altra possibilità è Linux sottosistema di controllo . Assicurarsi che il demone auditd sia avviato, quindi configurare ciò con cui si desidera accedere auditctl . Ogni operazione registrata viene registrata in /var/log/audit/audit.log (su distribuzioni tipiche). Per iniziare a guardare un determinato file:

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

Se si inserisce un watch in una directory, vengono guardati anche i file in essa contenuti e le sue sottodirectory ricorsivamente. Fare attenzione a non guardare la directory contenente i registri di controllo. È possibile limitare la registrazione a determinati processi, consultare la pagina man auditctl per i filtri disponibili. Devi essere root per usare il sistema di controllo.

Penso che tu voglia lsof (possibilmente convogliato ad un grep sul programma ed è bambini). Ti dirà ogni file a cui si accede attualmente sul filesystem. Per informazioni su quali file accedono per processo ( da qui ):

lsof -n -p `pidof your_app`
7
unclejamil

Ho provato che tracefile. Per me ha dato molte meno corrispondenze del mio strace ... | sed ... | sort -u. Ho anche aggiunto -s256 Alla riga di comando strace(1) ma non ha aiutato molto ...

Poi ho provato che loggedfs. Innanzitutto non è riuscito poiché non avevo accesso in lettura/scrittura alla directory in cui ho provato ad accedere. Dopo aver fatto chmod 755 temporaneamente ho avuto dei successi ...

Ma, per me, fare quanto segue sembra funzionare meglio:

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

E quindi postelaborare l'output dopo aver eseguito il processo di interesse.

Questo non rileva il processo di accesso ai file all'esterno di directory tracciata né questo non sa se qualche altro processo ha avuto accesso allo stesso albero di directory, ma in molti casi questo è uno strumento abbastanza buono per ottenere il lavoro fatto.

EDIT: inotifywait non rileva l'accesso al collegamento simbolico (solo gli obiettivi dopo che i collegamenti simbolici sono stati risolti). Sono stato colpito da questo quando ho archiviato le biblioteche accessibili da un programma per uso futuro. Ho usato un po 'di hacker Perl glob per scegliere i collegamenti simbolici lungo le librerie notificate per fare il lavoro in quel caso particolare.

EDIT2: almeno quando si inotificano file e collegamenti simbolici dalla riga di comando inotifywait (ad es. inotifywait -m file symlink O inotifywait symlink file) Mostrerà l'accesso a quale è il primo nella riga di comando (indipendentemente da quale file di symlink è accessibile). inotifywait non supporta IN_DONT_FOLLOW - che, quando ho provato a livello di programmazione, consente di vedere l'accesso a file (che può o meno essere quello che ci si aspetta ...) indipendentemente dall'ordine nella riga di comando

2
Tomi Ollila

Anche se potrebbe non darti abbastanza controllo (ancora?) Ho scritto un programma, che soddisfa almeno parzialmente le tue esigenze, usando fanotify e unshare del kernel linux per monitorare solo i file modificati (o letti) da un processo specifico e dai suoi figli . Rispetto allo strace, è abbastanza veloce (;

Può essere trovato su https://github.com/tycho-kirchner/shournal

Esempio su 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    
1
spawn