2009-01-07 11 views
11

En este momento estoy usando Exec para redirigir stderr a un registro de errores conAgregar texto a stderr vuelve a dirigir en bash

exec 2>> ${errorLog} 

El único inconveniente es que tengo que empezar cada carrera con un sello de tiempo desde exec simplemente empuja el texto directamente en el archivo de registro. ¿Hay alguna manera de redirigir el stderr pero permitirme agregarle texto, como una marca de tiempo?

Respuesta

16

Esto es muy interesante. Le he pedido a un tipo que sabe fiesta bastante bien, y me dijo de esta manera:

foo() { while IFS='' read -r line; do echo "$(date) $line" >> file.txt; done; }; 

En primer lugar, que crea una función que lee una línea de entrada sin procesar de la entrada estándar, mientras que la asignación de IFS hace que doesn' t ignora los espacios en blanco. Después de leer una línea, la emite con los datos apropiados adjuntos. Entonces usted tiene que decirle a bash para redirigir stderr en esa función:

exec 2> >(foo) 

todo lo que escribe en stderr ahora pasará a través de la función foo. Tenga en cuenta que cuando lo hace en un shell interactivo, ya no verá la solicitud, porque está impreso en stderr, y la lectura en foo está en línea amortiguada :)

+0

$ foo() {while IFS = '' lectura -r línea; hacer eco de "$ (date) $ line" >> file.txt; hecho; }; $ exec 2>> (foo) Advertencia: El programa '/ bin/bash' se bloqueó. whoops – Peter

+0

Pero si cambio eso a: echo 2 | tee> (foo), entonces funciona bien. – Peter

+0

En la pregunta, cada línea se agrega a un archivo ya abierto. En la respuesta, el archivo de registro se abre para cada línea. Y una búsqueda hasta el final del archivo también es necesaria. Puede ser mejor hacer un segundo 'exec' en' foo'. – ceving

1

Se podría sencilla sólo tiene que utilizar:

exec 1> >(sed "s/^/$(date '+[%F %T]'): /" | tee -a ${LOGFILE}) 2>&1 

Esto no va a resolver por completo el problema con respecto a Prompt no se muestra (ITT mostrará después de una poco tiempo, pero no en tiempo real, ya que la tubería guardará en caché algunos datos ...), pero mostrará la salida 1: 1 en stdout así como en el archivo.

El único problema es, que no podía resolver, es decir, para hacer esto de una función, ya que se abre un subnivel, donde el ejecutivo es inútil para el programa principal ...

+0

¿Con esto todas las líneas obtienen la misma marca de tiempo? – ceving

-1
cat q23123 2> tmp_file ;cat tmp_file | sed -e "s/^/$(date '+[%F %T]'): /g" >> output.log; rm -f tmp_file 
0

Este el ejemplo redirige stdout y stderr sin perder el stdout y el stderr originales. También los errores en el controlador stdout se registran en el controlador stderr. Los descriptores de archivo se guardan en variables y se cierran en los procesos secundarios. Bash cuida que no se produzcan colisiones.

#! /bin/bash 

stamp() 
{ 
    local LINE 
    while IFS='' read -r LINE; do 
    echo "$(date '+%Y-%m-%d %H:%M:%S,%N %z') $$ $LINE" 
    done 
} 

exec {STDOUT}>&1 
exec {STDERR}>&2 
exec 2> >(exec {STDOUT}>&-; exec {STDERR}>&-; exec &>> stderr.log; stamp) 
exec > >(exec {STDOUT}>&-; exec {STDERR}>&-; exec >> stdout.log; stamp) 

for n in $(seq 3); do 
    echo loop $n >&$STDOUT 
    echo o$n 
    echo e$n >&2 
done 

Esto requiere una versión actual Bash pero gracias a Shellshock se puede confiar en esto hoy en día.

Cuestiones relacionadas