Para saber cuánto tiempo tardan ciertas operaciones dentro de un script Bash (v4 +), me gustaría analizar el resultado del time
comando "por separado" y (en última instancia) capturarlo dentro de una variable Bash ( let VARNAME=...
).
Ahora, estoy usando time -f '%e' ...
(o más bien command time -f '%e' ...
debido al Bash incorporado), pero dado que ya redirijo la salida del comando ejecutado, realmente estoy perdido en cuanto a cómo capturaría la salida del time
comando. Básicamente, el problema aquí es separar la salida de time
la salida de los comandos ejecutados.
Lo que quiero es la funcionalidad de contar la cantidad de tiempo en segundos (enteros) entre el inicio de un comando y su finalización. No tiene que ser el time
comando o el respectivo incorporado.
Editar: dadas las dos respuestas útiles a continuación, quería agregar dos aclaraciones.
- No quiero tirar la salida del comando ejecutado, pero realmente no importará si termina en stdout o stderr.
- Preferiría un enfoque directo sobre uno indirecto (es decir, capturar la salida directamente en lugar de almacenarla en archivos intermedios).
La solución que utilizo date
hasta ahora se cierra a lo que quiero.
fuente
fork()
,execvp()
ywait3()/wait4()
. En última instancia, esto es lo que están haciendo el tiempo y los amigos. No conozco una manera simple de hacerlo en bash / perl sin redirigir a un archivo o enfoque similar.Respuestas:
Para obtener la salida de
time
en una var, use lo siguiente:También puede solicitar un solo tipo de hora, por ejemplo, utime:
Para obtener el tiempo que también puede usar
date +%s.%N
, tómelo antes y después de la ejecución y calcule la diferencia:fuente
DIFF=$((END-START))
, haciendo uso de las expresiones aritméticas. :) ... gracias por la respuesta. +1.%N
en el código de binfalse), necesitabc
cálculos más sofisticados.time (cmd) 2> something
funciona para redirigir la salida de temporizaciónfile
, no está destinado a (según la documentación), no lo hace en otros shells dondetime
hay una palabra clave y podría considerarse como un error . No confiaría en él, ya que puede no funcionar en futuras versiones debash
.En bash, el resultado de la
time
construcción va a su error estándar, y puede redirigir el error estándar de la tubería que afecta. Así que vamos a empezar con un comando que escribe a sus streamas de salida y de error:sh -c 'echo out; echo 1>&2 err'
. Para no mezclar la secuencia de error del comando con la salida detime
, podemos desviar temporalmente la secuencia de error del comando a un descriptor de archivo diferente:Esto escribe
out
en fd 1,err
en fd 3 y los tiempos en fd 2:Sería más agradable tenerlo
err
en fd 2 y las veces en fd 3, por lo que los intercambiamos, lo cual es engorroso porque no hay una forma directa de intercambiar dos descriptores de archivo:Esto muestra cómo puede postprocesar la salida del comando, pero si desea capturar tanto la salida del comando como sus tiempos, debe trabajar más duro. Usar un archivo temporal es una solución. De hecho, es la única solución confiable si necesita capturar tanto el error estándar del comando como su salida estándar. Pero de lo contrario, puede capturar todo el resultado y aprovechar el hecho de que
time
tiene un formato predecible (si lo usatime -p
para obtener el formato POSIX o laTIMEFORMAT
variable específica de bash ).Si solo le importa el tiempo del reloj de pared, la ejecución
date
antes y después es una solución simple (si es un poco más imprecisa debido al tiempo extra dedicado a cargar el comando externo).fuente
Con el tiempo, la salida del comando sale en stdout y el tiempo sale en stderr. Entonces, para separarlos, puedes hacer:
Pero, ahora el tiempo está en un archivo. No creo que Bash pueda poner stderr en una variable directamente. Si no le importa redirigir la salida del comando a alguna parte, puede hacer lo siguiente:
Cuando haga esto, la salida del comando estará activada
outputfile
y el tiempo que tardó en ejecutarse$FOO
.fuente
time
escrituras de stderr, pero no me di cuenta de que fusionaría stdout y stderr del comando ejecutado en su stdout. Pero, en general, ¿no hay un método directo (es decir, sin archivo intermedio)? +1.time
no combina sus comandosstdout
ystderr
. La forma en que lo mostré suponía que solo necesitabas la salida estándar del comando. Comobash
solo almacenará lo que salgastdout
, debe redirigir. En caso de que pueda soltar con seguridad el comando stderr: el tiempo siempre estará en la última línea de stderr. Si necesita las dos secuencias de salida de su comando, le sugiero que lo envuelva en otro script.Si está
bash
(y nosh
) y NO necesita una precisión de menos de un segundo, puede omitir la llamada pordate
completo y hacerlo sin generar ningún proceso adicional, sin tener que separar la salida combinada y sin tener que capturar y analizar la salida de cualquier comando:fuente
Para ese propósito, probablemente sea mejor usar
times
(quetime
) en elbash
que imprime el usuario acumulado y los tiempos del sistema para el shell y para los procesos ejecutados desde el shell, por ejemplo use:Ver:
help -m times
para más información.fuente
Al poner todas las respuestas anteriores juntas, cuando en OSX
puedes hacer como
fuente
Instalar
/bin/time
(por ejemplopacman -S time
)Entonces, en lugar de error al intentar
-f
marcar:Realmente puedes usarlo:
Y obtenga lo que desea: tiempo en variable (ejemplo, usos
%e
para el tiempo transcurrido real, para otras opciones de verificaciónman time
):fuente
/usr/bin/time
en muchos sistemastime
es un shell integrado en Bash (y presumiblemente otros shells), pero siempre quetime
esté la ruta al ejecutablePATH
, podemos usarlocommand time
para asegurarnos de que estamos ejecutando el comando externo en lugar del incorporado.Solo como un aviso al trabajar con las declaraciones anteriores y especialmente teniendo en cuenta la respuesta de Grzegorz. Me sorprendió ver en mi sistema Ubuntu 16.04 Xenial estos dos resultados:
No tengo ningún alias establecido, por lo que no sé por qué sucede esto.
fuente
time
También es una cáscara incorporada.command
, si desea asegurarse de que está ejecutando el comando incorporado, usebuiltin
. No hay magia aquí. Utilícelohelp
para descubrir los comandos disponibles otype <command>
para determinar qué tipo<command>
es (por ejemplo, un comando incorporado, un comando externo, una función o un alias).command
comando. Lo cual es un hecho asegura que se llame a / usr / bin / time. Esto significa que las siguientes dos declaraciones son compatibles:$ command time -f %e sleep 4
y$ /usr/bin/time -f %e sleep
intente esto, ejecuta un comando simple con argumentos y pone los tiempos $ real $ user $ sys y conserva el código de salida.
Tampoco bifurca subcapas ni pisotea ninguna variable, excepto el sistema de usuario real, y no interfiere con la ejecución del script
p.ej
nota: solo mide el tiempo del comando simple, no una tubería, cuyos componentes se ejecutan en una subshell
Esta versión le permite especificar como $ 1 el nombre de las variables que deberían recibir las 3 veces:
p.ej
y puede ser útil si termina siendo llamado de forma recursiva, para evitar pisotear a veces; pero luego rus, etc., deben declararse locales en su uso.
http://blog.sam.liddicott.com/2016/01/timeing-bash-commands.html
fuente