Ponga un texto delante de cada nueva línea que imprima un programa en stdout

9

Entonces, quiero hacer un registro y, por lo tanto, quiero poner una fecha delante de la salida de un script bash. El problema es que tiene múltiples líneas de salida. Solo puedo poner la fecha antes de toda la salida. Pero luego tengo una línea sin fecha en los registros. Por supuesto, puedo suponer que la fecha de la línea anterior es la misma, pero esperaba que hubiera una solución. ¡Gracias por adelantado!

Este es mi script que llama a otro script:

#!/bin/sh
echo $(date "+%F %T") : starting script
echo $(date "+%F %T") : $(./script.sh)
echo $(date "+%F %T") :script ended

Esta es la salida:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
second line of output
2012-07-26 15:35:17 : script ended

Y eso es lo que me gustaría tener:

2012-07-26 15:34:12 : starting script
2012-07-26 15:35:14 : First line of output
2012-07-26 15:35:15 : second line of output
2012-07-26 15:35:17 : script ended
tzippy
fuente
¿Supongo que no podrías simplemente cambiar el segundo guión?
jmetz
Nah, lamentablemente no. Por eso vine aquí.
tzippy

Respuestas:

9

Según una pregunta similar sobre Stack Overflow , hay 2 excelentes opciones.

awk ( respuesta )

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

anotar ( respuesta )

annotate es un pequeño script bash, que puede obtenerse directamente a través del enlace que se proporciona aquí o, en sistemas basados ​​en Debian, a través del paquete devscripts(en forma de annotate-output).

Oliver Salzburg
fuente
2

Puedes usar awk

./script.sh | awk '{ print d,$1}' "d=$(date "+%F %T")"

awktoma una secuencia de entrada y modifica su salida. Este script dice "imprimir d seguido de la salida original", luego se completa dcon la fecha.

Pablo
fuente
1
¿No evalúa esto la dateexpresión solo una vez también, para que todas esas líneas se impriman al mismo tiempo?
Daniel Beck
@DanielBeck Sí, lo hice: supuse que estaba recogiendo la fecha cada vez, pero acabo de terminar mi prueba lo suficientemente rápido
Paul
1

Esto imprimirá la fecha y hora actuales antes de cada línea de salida de ./script.sh:

set -f
./script.sh | while read -r LINE; do echo $(date "+%F %T") : "$LINE"; done
set +f

Cómo funciona

  • set -fdesactiva la expansión de bash (o echo *no imprime un asterisco real).

  • while read -r LINE; do ... doneguarda una línea de salida en la variable $LINEy se ejecuta ..., hasta que se procesen todas las líneas.

  • echo $ (fecha "+% F% T"): "$ LINE" imprime la línea con la hora y fecha actuales.

  • set +f vuelve a activar la expansión bash, por lo que no interferirá con el resto de su script bash.

Dennis
fuente
Se evalúa solo una vez, por lo que cada uno sedinserta la misma fecha, justo antes de comenzar el segundo script. Probablemente no sea lo que el usuario quiere ...
Daniel Beck
No creo que este intento funcione tampoco. AFAIK, toda la subshell se evalúa completamente primero, luego se recorre el ciclo. Así que ahora los tiempos son posteriores a la ejecución.
Daniel Beck
Su ejemplo no funciona, ya que solo retrasa la salida, no la ejecución de ls. Simplemente pruebe su script con lo siguiente script.sh: #!/bin/bash(nueva línea)echo 1 ; sleep 1 ; echo 2 ; sleep 2 ; echo 3 ; sleep 3 ; echo 4
Daniel Beck
Use readcon un whilebucle en lugar de un bucle for.
chepner
@chepner: Buena idea.
Dennis