¿Cómo redirigir la salida del comando de tiempo a un archivo en Linux?

202

Solo una pequeña pregunta sobre los programas de temporización en Linux: el comando time permite medir el tiempo de ejecución de un programa:

[ed@lbox200 ~]$ time sleep 1

real    0m1.004s
user    0m0.000s
sys     0m0.004s

Que funciona bien. Pero si trato de redirigir la salida a un archivo, falla.

[ed@lbox200 ~]$ time sleep 1 > time.txt

real    0m1.004s
user    0m0.001s
sys     0m0.004s

[ed@lbox200 ~]$ cat time.txt 
[ed@lbox200 ~]$ 

Sé que hay otras implementaciones de tiempo con la opción -o para escribir un archivo, pero mi pregunta es sobre el comando sin esas opciones.

Alguna sugerencia ?

ed82
fuente
3
Posible duplicado del tiempo de ejecución de escritura de script bash en un archivo , y estoy lejos de estar convencido de que esta es la primera pregunta.
Jonathan Leffler
1
Este es un duplicado de stackoverflow.com/questions/2408981/…
codeforester

Respuestas:

266

Tratar

{ time sleep 1 ; } 2> time.txt

que combina el STDERR de "tiempo" y su comando en time.txt

O usar

{ time sleep 1 2> sleep.stderr ; } 2> time.txt

que pone STDERR de "sleep" en el archivo "sleep.stderr" y solo STDERR de "time" entra en "time.txt"

enero
fuente
2
Gracias, eso responde precisamente a mi pregunta. Si entendí correctamente, ¿el resultado del comando de tiempo se puede obtener de stderr?
ed82
77
Sí, pero debe ponerlo entre llaves, de lo contrario la redirección será parte del comando que timeevalúa.
Enero
55
@Daniel Siempre puedes redirigir la salida del comando interno por separado (es decir, {time sleep 1 2> sleepStdErr.txt;} 2> time.txt) y eso solo te proporcionaría la salida de tiempo. No estoy seguro de si hay una manera de obtenerlo independientemente de lo contrario.
gms7777
10
Si desea utilizar el tiempo con algo como grep que se lee en stdout intente { time sleep 1; } 2>&1 | grep real. Esto envía stderr a stdout que grep puede leer.
clayzermk1
9
NO olvides el ';' antes de cerrar '}', NO funcionará sin (lo hice, y ... me pregunto por qué no funciona :))
THESorcerer
38

Envolver time y el comando que está sincronizando en un conjunto de paréntesis.

Por ejemplo, los siguientes tiempos lsy escribe el resultado lsy los resultados del tiempo en outfile:

$ (time ls) > outfile 2>&1

O, si desea separar la salida del comando de la salida capturada de time:

$ (time ls) > ls_results 2> time_results
sampson-chen
fuente
12
No es necesario introducir una subshell aquí.
Enero
1
@ sampson-chen Eso solo funciona porque ls no escribe nada para stderr ¿verdad? ¿Cómo "separaría" la salida de 'tiempo' de la del comando a ejecutar si el comando escribe tanto en stdout como en stderr?
David Doria el
36

Sencillo. La timeutilidad GNU tiene una opción para eso.

Pero debe asegurarse de no estar utilizando el timecomando incorporado de su shell , ¡al menos el bashincorporado no proporciona esa opción! Es por eso que necesita dar la ruta completa de la timeutilidad:

/usr/bin/time -o time.txt sleep 1
cmaster - restablecer monica
fuente
También puede usar el no incorporado sin especificar la ruta completa: stackoverflow.com/questions/29540540/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
14

Si le preocupa la salida de error del comando, puede separarlos de esta manera mientras sigue usando el comando de tiempo incorporado.

{ time your_command 2> command.err ; } 2> time.log

o

{ time your_command 2>1 ; } 2> time.log

Como ve, los errores del comando van a un archivo (ya que stderrse usa para time).

Desafortunadamente, no puede enviarlo a otro identificador (como 3>&2) ya que eso ya no existirá fuera del{...}

Dicho esto, si puedes usar el tiempo GNU, solo haz lo que @Tim Ludwinski dijo.

\time -o time.log command
marca
fuente
8

Dado que la salida del comando 'tiempo' es salida de error, rediríjalo ya que la salida estándar sería más intuitiva para realizar un procesamiento adicional.

{ time sleep 1; } 2>&1 |  cat > time.txt
jaycee xu
fuente
6

Si está utilizando el tiempo GNU en lugar del bash incorporado, intente

time -o outfile command

(Nota: el formato de tiempo GNU es un poco diferente al bash incorporado).

Tim Ludwinski
fuente
1
Esto gracias. Y puede usar \time -o outfile command(con ``) para usar GNU en lugar de incorporado.
Marque el
3
&>out time command >/dev/null

en tu caso

&>out time sleep 1 >/dev/null

luego

cat out
alinsoar
fuente
3
Idea elegante, pero lleva a que el shell no use su comando incorporado. Si no tiene un timebinario real instalado, outcontendrá algo como bash: time: command not found.
scy
Además, el formato para el tiempo GNU no es el mismo que el bash incorporado, lo que causa problemas para el análisis automático.
Guss
3

Terminé usando:

/usr/bin/time -ao output_file.txt -f "Operation took: %E" echo lol
  • Donde se agrega "a"
  • Donde "o" es procesado por el nombre del archivo para adjuntar a
  • Donde "f" es formato con una sintaxis similar a printf
  • Donde "% E" produce 0:00:00; horas: minutos: segundos
  • Tuve que invocar / usr / bin / time porque el "tiempo" bash lo estaba pisoteando y no tiene las mismas opciones
  • Solo estaba tratando de obtener la salida al archivo, no es lo mismo que OP
Locane
fuente
2
#!/bin/bash

set -e

_onexit() {
    [[ $TMPD ]] && rm -rf "$TMPD"
}

TMPD="$(mktemp -d)"
trap _onexit EXIT

_time_2() {
    "$@" 2>&3
}

_time_1() {
    time _time_2 "$@"
}

_time() {
    declare time_label="$1"
    shift
    exec 3>&2
    _time_1 "$@" 2>"$TMPD/timing.$time_label"
    echo "time[$time_label]"
    cat "$TMPD/timing.$time_label"
}

_time a _do_something
_time b _do_another_thing
_time c _finish_up

Esto tiene el beneficio de no generar subcapas, y la tubería final tiene su stderr restaurado al stderr real.

Adam Heath
fuente
0

Si no desea tocar el proceso original 'stdout y stderr, puede redirigir stderr al descriptor de archivo 3 y viceversa:

$ { time { perl -le "print 'foo'; warn 'bar';" 2>&3; }; } 3>&2 2> time.out
foo
bar at -e line 1.
$ cat time.out

real    0m0.009s
user    0m0.004s
sys     0m0.000s

Puede usar eso para un contenedor (por ejemplo, para cronjobs) para monitorear tiempos de ejecución:

#!/bin/bash

echo "[$(date)]" "$@" >> /my/runtime.log

{ time { "$@" 2>&3; }; } 3>&2 2>> /my/runtime.log
Tobias Gödderz
fuente
0

Si está usando csh, puede usar:

/usr/bin/time --output=outfile -p $SHELL  -c 'your command'

Por ejemplo:

/usr/bin/time --output=outtime.txt -p csh -c 'cat file'
Leo Cardona
fuente