web-dev-qa-db-fra.com

Ecrire la sortie "tail -f" dans un autre fichier

En prolongement de mon dernier message où j’ai utilisé grep & tail -f pour rechercher des occurrences d’événements "rares". Je voudrais enregistrer cela dans un autre fichier.

J'ai essayé de tourner

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

dans

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

Le fichier est créé, mais rien n'est rempli. S'agit-il d'un problème de mise en cache ou autre? Comment pourrais-je obtenir une annexe en temps réel de la sortie de ma queue dans un nouveau fichier?

31
Mike

La mise en mémoire tampon est le problème.

Faites-le de cette façon

 tail -f log.txt | egrep --line-buffered 'WARN | ERROR' | tee filter_output.txt 
 # ^^^^^^^^^^^^^^^. 

Confirmé de travailler sur Cygwin aussi.

41
nik

C'est probablement un problème de mise en mémoire tampon. Voir cet article SO pour désactiver la mise en mémoire tampon automatique lors de l'utilisation de canaux . Vous pouvez utiliser la commande unbuffer à partir de expect:

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

Edit : Comme vous avez un pipeline plus long, vous devez probablement annuler chaque tampon (sauf la dernière):

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

Edit 2 : unbuffer est disponible sur Cygwin à partir du paquet source expect (par exemple expect-20030128-1-src.tar.bz2 , trouvé dans le dossier expect/examples), mais c'est un script très court. Si le paquetage expect est déjà installé, mettez-le simplement dans un script appelé unbuffer dans votre répertoire /usr/local/bin:

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

eval spawn -noecho $argv
set timeout -1
expect

Sur Debian, la commande unbuffer est fournie dans le paquet expect-dev et est installée en tant que expect_unbuffer.

5
quack quixote

Lorsque vous utilisez une commande qui ne "termine" pas vraiment (telle que tail -f), cela ne fonctionne pas vraiment ou très bien (pas du tout).

Vous devriez pouvoir rediriger la sortie vers un fichier texte. Essaye ça:

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

Comme d'autres l'ont déjà souligné, vous pouvez utiliser l'utilitaire unbuffer de Expect.

Notez cependant que, selon votre système et la version disponible d'Expect, vous devrez peut-être utiliser le commutateur -p pour annuler la mémoire tampon. Citer la page de manuel:

   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

Donc, vous pourriez avoir besoin de cette invocation:

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

BTW, voir cet article pour une explication détaillée du problème de mise en mémoire tampon de la sortie: http://www.pixelbeat.org/programming/stdio_buffering/

2
Aleksander Adamowski

Ceci est la version de unbuffer que j'ai:

#!/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
}
2
Dennis Williamson