Escribir la salida "tail -f" en otro archivo

34

Como continuación de mi último post donde solía grep & tail -fencontrar eventos de eventos "raros". Me gustaría grabar esto en otro archivo.

He intentado girar

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

dentro

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

El archivo se crea, pero no se rellena nada, ¿es esto un problema de almacenamiento en caché o no? ¿Cómo obtendría un anexo en tiempo real de la salida de mi cola a un nuevo archivo?

Micro
fuente

Respuestas:

44

El almacenamiento en búfer es el problema.

Hacerlo de esta forma,

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

Confirmado para trabajar en Cygwin también.

nik
fuente
6

Probablemente sea un problema de almacenamiento en búfer. Vea esta publicación SO sobre cómo deshabilitar el almacenamiento en búfer automático cuando se usan tuberías . Puede usar el unbuffercomando desde expect:

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

Editar : dado que tiene una tubería más larga, es probable que necesite liberar el búfer de cada comando (excepto el último):

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

Edición 2 : unbufferestá disponible en Cygwin desde el expectpaquete fuente (por ejemplo, expect-20030128-1-src.tar.bz2 , que se encuentra en la expect/examplescarpeta), pero es un script muy corto. Si ya tiene el expectpaquete instalado, simplemente colóquelo en un script llamado unbufferen su /usr/local/bindirectorio:

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

eval spawn -noecho $argv
set timeout -1
expect

En Debian, el unbuffercomando se proporciona en el expect-devpaquete y se instala como expect_unbuffer.

quijote curandero
fuente
¿Hay alguna manera de lograr esto con Cygwin?
Mike
información adicional sobre el uso en cygwin; Necesitarás el expectpaquete.
quack quijote
Gracias, no puedo probar hasta el lunes ahora tristemente. Se actualizará entonces.
Mike
4

Cuando se usa un comando que realmente no 'termina' (como tail -f), esto realmente no funciona o no funciona bien (en absoluto).

Debería poder redirigir la salida a un archivo de texto. Prueba esto:

tail -f log.txt | egrep 'WARN|ERROR' > filtered_output.txt
Josh Hunt
fuente
1
Esto no parece funcionar.
Mike
2

Esta es la versión de la unbufferque tengo:

#!/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
}
Pausado hasta nuevo aviso.
fuente
+1 gracias por la información adicional. No sé si es amigable para Cygwin pero parece un script más inteligente.
quack quijote
2

Como otros han señalado, puede usar la unbufferutilidad de Expect.

Sin embargo, tenga en cuenta que, dependiendo de su sistema y la versión disponible de Expect, es posible que necesite usar el -pinterruptor para eliminar el búfer. Citando la página del manual:

   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

Entonces puede que necesite esta invocación:

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

Por cierto, consulte este artículo para obtener una explicación detallada del problema del búfer de salida: http://www.pixelbeat.org/programming/stdio_buffering/

Aleksander Adamowski
fuente