Zapisywanie wyniku „tail -f” do innego pliku

34

Jako kontynuacja mojego ostatniego postu, w którym grep & tail -fznajdowałem przypadki „rzadkich” wydarzeń. Chciałbym zapisać to w innym pliku.

Próbowałem się odwrócić

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

w

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

Plik zostanie utworzony, ale nic nie zostanie wypełnione, czy jest to problem z pamięcią podręczną? W jaki sposób mogę dołączyć dane wyjściowe mojego ogona w czasie rzeczywistym do nowego pliku?

Mikrofon
źródło

Odpowiedzi:

44

Problem stanowi buforowanie.

Zrób to w ten sposób

tail -f log.txt | egrep - buforowany wierszowo „WARN | ERROR” | tee filter_output.txt
# ^^^^^^^^^^^^^^^

Potwierdzono także pracę nad Cygwinem.

nik
źródło
6

Prawdopodobnie jest to problem buforowania. Zobacz ten post SO dotyczący wyłączania automatycznego buforowania podczas korzystania z potoków . Możesz użyć unbufferpolecenia z expect:

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

Edycja : Ponieważ masz dłuższy potok, prawdopodobnie musisz cofnąć buforowanie każdego polecenia (z wyjątkiem ostatniego):

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

Edycja 2 : unbufferjest dostępna w Cygwin z expectpakietu źródłowego (np. Expect-20030128-1-src.tar.bz2 , znaleziony w expect/examplesfolderze), ale jest to bardzo krótki skrypt. Jeśli masz expectjuż zainstalowany pakiet, po prostu umieść go w skrypcie wywoływanym unbufferw /usr/local/binkatalogu:

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

eval spawn -noecho $argv
set timeout -1
expect

W systemie Debian unbufferpolecenie znajduje się w expect-devpakiecie i jest instalowane jako expect_unbuffer.

quack quixote
źródło
czy jest sposób na osiągnięcie tego za pomocą cygwina?
Mike
dodano informacje o korzystaniu z cygwina; będziesz potrzebować expectpaczki.
quack quixote
Dzięki, nie mogę niestety spróbować do poniedziałku. Zaktualizuje wtedy.
Mike
4

Gdy używasz polecenia, które tak naprawdę „nie kończy” (np. tail -f), To tak naprawdę nie działa lub wcale nie jest tak dobre (wcale).

Powinieneś być w stanie przekierować wyjście do pliku tekstowego. Spróbuj tego:

tail -f log.txt | egrep 'WARN|ERROR' > filtered_output.txt
Josh Hunt
źródło
1
To nie działa.
Mike
2

Oto unbuffermoja wersja :

#!/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
}
Wstrzymano do odwołania.
źródło
+1 dzięki za dodatkowe informacje. nie wiem, czy jest przyjazny dla cygwina, ale wygląda na bardziej inteligentny skrypt.
quack quixote
2

Jak zauważyli inni, możesz użyć unbuffernarzędzia z Expect.

Należy jednak pamiętać, że w zależności od systemu i dostępnej wersji programu Expect może być konieczne użycie -pprzełącznika w celu cofnięcia buforowania. Powołując się na stronę podręcznika:

   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

Może więc być potrzebne to wywołanie:

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

BTW, zobacz ten artykuł, aby uzyskać szczegółowe wyjaśnienie problemu buforowania danych wyjściowych: http://www.pixelbeat.org/programming/stdio_buffering/

Aleksander Adamowski
źródło