2011-08-23 6 views
532

È possibile utilizzare grep su un flusso continuo?Come "grep" un flusso continuo?

Ciò che intendo è una sorta di comando tail -f <file>, ma con grep sull'output per mantenere solo le linee che mi interessano.

Ho provato tail -f <file> | grep pattern ma sembra che grep può essere eseguito solo una volta tail finiture, vale a dire mai.

+29

'tail -f file | grep pattern' dovrebbe funzionare bene. –

+8

È molto probabile che il programma che genera il file non stia scaricando l'output. –

+0

'tail -f file' funziona (vedo il nuovo output in tempo reale) –

risposta

989

Attiva la modalità di bufferizzazione linea grep.

+26

Questa dovrebbe essere la risposta accettata. – Patryk

+2

cosa succede se accodo un file di registro che viene ruotato mentre è in esecuzione? Logrotate sarà in grado di ruotare il file? –

+3

@MichaelNiemand potresti usare tail -F file | grep --line-buffered my_pattern – jcfrei

97

Io uso il tail -f <file> | grep <pattern> tutto il tempo.

Attenderà fino a quando grep svuota, non finché non finisce (sto usando Ubuntu).

+3

Che può durare un po ', quindi cerca di non diventare impaziente. – glglgl

+0

Quanto ci vuole? –

+0

@Matthieu: dipende principalmente da cosa si vuole e quanto sono grandi i buffer sul proprio sistema operativo. Se grep corrisponde solo a una stringa breve ogni poche ore, saranno giorni prima del primo flush. – tripleee

0

Sì, funzionerà correttamente. Grep e la maggior parte dei comandi Unix operano su flussi una riga alla volta. Ogni linea che esce dalla coda verrà analizzata e trasmessa se corrisponde.

+1

Questo non è effettivamente corretto. Se 'grep' è l'ultimo comando nella pipe chain, agirà come tu spieghi. Tuttavia, se è nel mezzo, buffererà circa 8k di output alla volta. –

47

Penso che il tuo problema è che grep utilizza un buffer di output. Prova

tail -f file | stdbuf -o0 grep my_pattern 

imposta la modalità di buffer di uscita di grep su unbuffered.

+5

E questo ha il vantaggio che può essere usato per molti altri comandi oltre a 'grep'. –

+4

Tuttavia, come ho scoperto dopo aver giocato di più con esso, alcuni comandi scaricano solo il loro output quando sono connessi a un tty, e per questo, 'unbuffer' (nel pacchetto' expect-dev' su debian) è * king *. Quindi userei unbuffer su stdbuf. –

+4

@Peter V. Mørch Sì, hai ragione, unbuffer può a volte funzionare dove stdbuf non può. Ma penso che tu stia cercando di trovare un programma "magico" che risolverà sempre i tuoi problemi invece di capire il tuo problema. La creazione di un tty virtuale è un'attività non correlata. Stdbuf fa esattamente ciò che vogliamo (imposta il buffer di output standard per dare valore), mentre unbuffer fa un sacco di cose nascoste che potremmo non volere (confronta interattivo 'top' con stdbuf e unbuffer). E in realtà non esiste una soluzione "magica": a volte anche unbuffer non funziona, ad esempio awk utilizza un'implementazione diversa del buffer (anche stdbuf fallirà). – XzKto

-3

Utilizzare awk (un'altra grande utilità di bash) invece di grep in cui non si dispone dell'opzione bufferizzata di linea! Trasmetterà continuamente i tuoi dati dalla coda.

questo è come si utilizza grep

tail -f <file> | grep pattern 

Ecco come si può usare awk

tail -f <file> | awk '/pattern/{print $0}' 
+5

Questo non è corretto; Awk out of the box esegue il buffering di linea, proprio come la maggior parte degli altri strumenti Unix standard. (Inoltre, '{print $ 0}' è ridondante, poiché la stampa è l'azione predefinita quando passa una condizione.) – tripleee

4

Nella maggior parte dei casi, è possibile tail -f /var/log/some.log |grep foo e funzionerà bene.

Se è necessario utilizzare più greps su un file di log in esecuzione e si scopre che si ottiene nessun output, potrebbe essere necessario attaccare l'interruttore --line-buffered nella vostra mezzo grep (s), in questo modo:

tail -f /var/log/some.log | grep --line-buffered foo | grep bar 
1

si può considerare questa risposta come la valorizzazione .. di solito sto usando

tail -F <fileName> | grep --line-buffered <pattern> -A 3 -B 5 

-F è migliore in caso di file di rotazione (-f non funziona correttamente se il file ruotato)

-A e -B è utile per ottenere linee appena prima e dopo l'occorrenza del modello.questi blocchi apparsi tra separatori di linea tratteggiata

+1

'grep -C 3 ', sostituisce -A e -B se N è uguale. –

-1

sed sarebbe l'apposito comando (flusso editore)

tail -n0 -f <file> | sed -n '/search string/p'

e quindi se si voleva il comando tail per uscire una volta che hai trovato una particolare stringa:

tail --pid=$(($BASHPID+1)) -n0 -f <file> | sed -n '/search string/{p; q}'

Ovviamente una da bash: $ BASH PID sarà l'id di processo del comando tail. Il comando sed è il prossimo dopo tail nella pipe, quindi l'id del processo sed sarà $ BASHPID + 1.

+1

L'ipotesi che il prossimo processo avviato sul sistema ('$ BASHPID + 1') sia tuo è falso in molte situazioni, e questo non fa nulla per risolvere il problema del buffer che è probabilmente quello che l'OP stava cercando di chiedere. In particolare, raccomandare 'sed' su' grep' qui sembra semplicemente una questione di preferenza (dubbia). (Puoi ottenere il comportamento di 'p; q' con' grep -m 1' se è questo il punto che stai tentando di consegnare.) – tripleee

2

Se si vuole trovare corrispondenze in tutto il file (non solo la coda), e lo si vuole per sedersi e aspettare per i nuovi incontri, questo funziona bene:

tail -c +0 -f <file> | grep --line-buffered <pattern> 

Il -c +0 bandiera dice che l'output dovrebbe iniziare 0 byte (-c) dall'inizio (+) del file.