Deseo anteponer una marca de tiempo a cada línea de salida de un comando. Por ejemplo:
foo
bar
baz
se convertiría
[2011-12-13 12:20:38] foo
[2011-12-13 12:21:32] bar
[2011-12-13 12:22:20] baz
... donde el tiempo prefijado es el tiempo en que se imprimió la línea. ¿Cómo puedo conseguir esto?
Respuestas:
moreutils incluye lo
ts
que hace esto bastante bien:command | ts '[%Y-%m-%d %H:%M:%S]'
También elimina la necesidad de un bucle, cada línea de salida tendrá una marca de tiempo.
¿Quiere saber cuándo volvió a funcionar ese servidor que reinició? Solo corre
ping | ts
, problema resuelto: D.fuente
tail -f /tmp/script.results.txt | ts
ssh -v 127.0.0.1 2>&1 | ts
-s
es útil. Como eso muestra el tiempo de ejecución del comando. Personalmente me gusta usar ambosts
yts -s
al mismo tiempo. Se ve algo como esto:command | ts -s '(%H:%M:%.S)]' | ts '[%Y-%m-%d %H:%M:%S'
. Esto antepone las líneas de registro de esta manera:[2018-12-04 08:31:00 (00:26:28.267126)] Hai <3
En primer lugar, si espera que estas marcas de tiempo realmente representen un evento, tenga en cuenta que dado que muchos programas realizan el almacenamiento en línea (algunos de forma más agresiva que otros), es importante pensar en esto como cerca del tiempo que tendría la línea original impreso en lugar de una marca de tiempo de una acción que tiene lugar.
También puede verificar que su comando no tenga una función incorporada dedicada a hacer esto. Como ejemplo,
ping -D
existe en algunasping
versiones e imprime el tiempo transcurrido desde la época de Unix antes de cada línea. Sin embargo, si su comando no contiene su propio método, existen algunos métodos y herramientas que pueden emplearse, entre otros:Shell POSIX
Tenga en cuenta que, dado que muchos shells almacenan sus cadenas internamente como cstrings, si la entrada contiene el carácter nulo (
\0
), puede hacer que la línea finalice prematuramente.GNU awk
Perl
Pitón
Rubí
fuente
stdbuf -o 0
, pero si el programa maneja manualmente su almacenamiento en búfer de salida, no ayudará (a menos que haya una opción para deshabilitar / reducir el tamaño del búfer de salida).python -u
... for x in sys.stdin
itera sobre las líneas sin almacenarlas primero en la memoria intermedia.Para una medición delta línea por línea, pruebe gnomon .
fuente
ts
cuando se utilizan procesos en vivo. Mientras quets
es más adecuado para procesos no interactivos.La publicación de Ryan proporciona una idea interesante, sin embargo, falla en varios aspectos. Mientras probaba
tail -f /var/log/syslog | xargs -L 1 echo $(date +'[%Y-%m-%d %H:%M:%S]') $1
, noté que la marca de tiempo se mantiene igual, incluso sistdout
llega más tarde con una diferencia de segundos. Considere esta salida:Mi solución propuesta es similar, sin embargo, proporciona una marca de tiempo adecuada y utiliza algo más portátil en
printf
lugar deecho
¿Por qué
bash -c '...' bash
? Debido a la-c
opción, el primer argumento se asigna$0
y no aparecerá en la salida. Consulte la página del manual de su shell para obtener la descripción adecuada de-c
Probar esta solución con
tail -f /var/log/syslog
y (como probablemente podría adivinar) desconectarse y volver a conectarse a mi wifi, ha mostrado la marca de tiempo adecuada proporcionada por ambosdate
y lossyslog
mensajesBash podría ser reemplazado por cualquier caparazón similar a bourne, podría hacerse con cualquiera
ksh
odash
, al menos, aquellos que tienen-c
opción.Problemas potenciales:
La solución requiere tener
xargs
, que está disponible en sistemas compatibles con POSIX, por lo que la mayoría de los sistemas tipo Unix deberían estar cubiertos. Obviamente no funcionará si su sistema no es compatible con POSIX o no tieneGNU findutils
fuente
Hubiera preferido comentar más arriba, pero no puedo, reputacionalmente. De todos modos, la muestra Perl anterior se puede quitar de la siguiente manera:
El primer '$ |' desabrocha STDOUT. El segundo establece stderr como el canal de salida predeterminado actual y lo desactiva. Dado que select devuelve la configuración original de $ |, al ajustar el select dentro de un select, también restablecemos $ | por defecto, STDOUT.
Y sí, puedes cortar y pegar como está. Lo forcé en varias líneas para mayor legibilidad.
Y si realmente quieres ser preciso (y tienes Time :: Hires instalado):
fuente
La mayoría de las respuestas sugieren usar
date
, pero es lo suficientemente lento. Si su versión bash es superior a 4.2.0, es mejor usarlaprintf
, es un bash incorporado. Si necesita admitir versiones de bash heredadas, puede crear unalog
función que depende de la versión de bash:Ver diferencias de velocidad:
UPD: en lugar de
$(date +"${TIMESTAMP_FORMAT}")
hacerlo, es mejor usarlo$(exec date +"${TIMESTAMP_FORMAT}")
o incluso$(exec -c date +"${TIMESTAMP_FORMAT}")
acelerar la ejecución.fuente
Puedes hacer esto con
date
yxargs
:Explicación:
xargs -L 1
le dice a xargs que ejecute el comando en curso para cada 1 línea de entrada, y pasa en la primera línea cuando lo hace.echo `date +'[%Y-%m-%d %H:%M:%S]'` $1
básicamente hace eco de la fecha con el argumento de entrada al finalfuente
$1
. Eso no es buen estilo. Siempre cite las variables. Además, está utilizandoecho
, que no es portátil. Está bien, pero puede no funcionar correctamente en algunos sistemas.date
reevaluar cada línea, o es casi imposible?