Quiero time
un comando que consta de dos comandos separados con una salida de tubería a otra. Por ejemplo, considere los dos scripts a continuación:
$ cat foo.sh
#!/bin/sh
sleep 4
$ cat bar.sh
#!/bin/sh
sleep 2
Ahora, ¿cómo puedo time
informar el tiempo que lleva foo.sh | bar.sh
(y sí, sé que la tubería no tiene sentido aquí, pero esto es solo un ejemplo)? Funciona como se esperaba si los ejecuto secuencialmente en una subshell sin tuberías:
$ time ( foo.sh; bar.sh )
real 0m6.020s
user 0m0.010s
sys 0m0.003s
Pero no puedo hacer que funcione cuando canalizo:
$ time ( foo.sh | bar.sh )
real 0m4.009s
user 0m0.007s
sys 0m0.003s
$ time ( { foo.sh | bar.sh; } )
real 0m4.008s
user 0m0.007s
sys 0m0.000s
$ time sh -c "foo.sh | bar.sh "
real 0m4.006s
user 0m0.000s
sys 0m0.000s
He leído una pregunta similar ( ¿Cómo ejecutar el tiempo en múltiples comandos Y escribir la salida de tiempo en el archivo? ) Y también probé el time
ejecutable independiente :
$ /usr/bin/time -p sh -c "foo.sh | bar.sh"
real 4.01
user 0.00
sys 0.00
Ni siquiera funciona si creo un tercer script que solo ejecuta la tubería:
$ cat baz.sh
#!/bin/sh
foo.sh | bar.sh
Y luego cronometra que:
$ time baz.sh
real 0m4.009s
user 0m0.003s
sys 0m0.000s
Curiosamente, no parece que time
salga tan pronto como se complete el primer comando. Si cambio bar.sh
a:
#!/bin/sh
sleep 2
seq 1 5
Y, de time
nuevo, esperaba que la time
salida se imprimiera antes seq
pero no lo es:
$ time ( { foo.sh | bar.sh; } )
1
2
3
4
5
real 0m4.005s
user 0m0.003s
sys 0m0.000s
Parece time
que no cuenta el tiempo que tardó en ejecutarse a bar.sh
pesar de esperar a que termine antes de imprimir su informe 1 .
Todas las pruebas se ejecutaron en un sistema Arch y utilizando bash 4.4.12 (1) -release. Solo puedo usar bash para el proyecto del que forma parte, por lo que incluso si zsh
algún otro poderoso shell puede evitarlo, esa no será una solución viable para mí.
Entonces, ¿cómo puedo obtener el tiempo que tardó en ejecutarse un conjunto de comandos canalizados? Y, mientras estamos en eso, ¿por qué no funciona? Parece que time
sale inmediatamente tan pronto como el primer comando ha terminado. ¿Por qué?
Sé que puedo obtener los tiempos individuales con algo como esto:
( time foo.sh ) 2>foo.time | ( time bar.sh ) 2> bar.time
Pero aún me gustaría saber si es posible cronometrar todo como una sola operación.
1 Esto no parece ser un problema de memoria intermedia, he intentado ejecutar los scripts con unbuffered
y stdbuf -i0 -o0 -e0
y el número todavía se imprimieron antes de la time
salida.