Scrivere l'output "tail -f" su un altro file


34

Come continuazione del mio ultimo post in cui ho grep & tail -ftrovato ricorrenze di eventi "rari". Vorrei registrarlo in un altro file.

Ho provato a girare

tail -f log.txt | egrep 'WARN|ERROR'

in

tail -f log.txt | egrep 'WARN|ERROR' | tee filtered_output.txt

Il file viene creato, ma non viene popolato nulla, si tratta di un problema di memorizzazione nella cache o in altro modo? Come potrei ottenere un accodamento in tempo reale dell'output della mia coda a un nuovo file?

Risposte:


44

Il buffering è il problema.

Fallo in questo modo,

tail -f log.txt | egrep - bufferizzato in linea 'WARN | ERROR' | tee filtered_output.txt
# ^^^^^^^^^^^^^^^

Confermato di lavorare anche su Cygwin.


6

È probabilmente un problema di buffering. Vedi questo post SO sulla disabilitazione del buffering automatico quando si usano le pipe . Puoi usare il unbuffercomando da expect:

$ unbuffer tail -f log.txt | egrep 'WARN|ERROR' | tee filtered_output.txt

Modifica : poiché hai una pipeline più lunga, probabilmente dovrai decomprimere ogni comando (tranne l'ultimo):

$ unbuffer tail -f log.txt | unbuffer egrep 'WARN|ERROR' | tee filtered_output.txt

Modifica 2 : unbufferè disponibile su Cygwin dal expectpacchetto sorgente (ad es. Prevedere-20030128-1-src.tar.bz2 , che si trova nella expect/examplescartella), ma è uno script molto breve. Se il expectpacchetto è già installato, è sufficiente inserirlo in uno script chiamato unbuffernella /usr/local/bindirectory:

#!/usr/bin/expect --
# Description: unbuffer stdout of a program
# Author: Don Libes, NIST

eval spawn -noecho $argv
set timeout -1
expect

Su Debian, il unbuffercomando è fornito nel expect-devpacchetto ed è installato come expect_unbuffer.


c'è un modo per ottenere questo risultato con cygwin?
Mike,

aggiunte informazioni sull'uso in cygwin; avrai bisogno del expectpacchetto.
Quack Quixote,

Grazie, non ci posso provare fino a lunedì, purtroppo. Si aggiornerà quindi.
Mike,

4

Quando si utilizza un comando che non "finisce" (come tail -f), in realtà non funziona o funziona così bene (per niente).

Dovresti essere in grado di reindirizzare l'output su un file di testo. Prova questo:

tail -f log.txt | egrep 'WARN|ERROR' > filtered_output.txt

1
Questo non sembra funzionare.
Mike,

2

Questa è la versione unbufferche ho:

#!/usr/bin/expect --
# Description: unbuffer stdout of a program
# Author: Don Libes, NIST

if {[string compare [lindex $argv 0] "-p"] == 0} {
    # pipeline
    set stty_init "-echo"
    eval spawn -noecho [lrange $argv 1 end]
    close_on_eof -i $user_spawn_id 0
    interact {
    eof {
        # flush remaining output from child
        expect -timeout 1 -re .+
        return
    }
    }
} else {
    set stty_init "-opost"
    set timeout -1
    eval spawn -noecho $argv
    expect
}

+1 grazie per le informazioni aggiuntive. non so se è compatibile con Cygwin ma sembra una sceneggiatura più intelligente.
Quack Quixote,

2

Come altri hanno sottolineato, è possibile utilizzare l' unbufferutilità da Expect.

Si noti, tuttavia, che a seconda del sistema e della versione disponibile di Expect, potrebbe essere necessario utilizzare l' -pinterruttore per unbuffer. Citando la pagina man:

   Normally, unbuffer does not read from stdin.  This simplifies use of unbuffer in some situations.  To use unbuffer in a  pipeline,  use
   the -p flag.  Example:

           process1 | unbuffer -p process2 | process3

Quindi potresti aver bisogno di questa invocazione:

unbuffer -p tail -f log.txt | unbuffer -p egrep 'WARN|ERROR' | tee filtered_output.txt

A proposito, vedi questo articolo per una spiegazione approfondita del problema del buffering dell'output: http://www.pixelbeat.org/programming/stdio_buffering/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.