Eu quero time
um comando que consiste em dois comandos separados com uma saída de tubulação para outra. Por exemplo, considere os dois scripts abaixo:
$ cat foo.sh
#!/bin/sh
sleep 4
$ cat bar.sh
#!/bin/sh
sleep 2
Agora, como posso time
relatar o tempo gasto foo.sh | bar.sh
(e sim, eu sei que o tubo não faz sentido aqui, mas este é apenas um exemplo)? Funciona como esperado se eu executá-los sequencialmente em um subshell sem canalizar:
$ time ( foo.sh; bar.sh )
real 0m6.020s
user 0m0.010s
sys 0m0.003s
Mas não consigo fazê-lo funcionar durante a tubulação:
$ 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
Eu li uma pergunta semelhante ( como executar o tempo em vários comandos E gravar a saída do tempo no arquivo? ) E também tentei o time
executável independente :
$ /usr/bin/time -p sh -c "foo.sh | bar.sh"
real 4.01
user 0.00
sys 0.00
Nem funciona se eu criar um terceiro script que execute apenas o pipe:
$ cat baz.sh
#!/bin/sh
foo.sh | bar.sh
E então cronometre isso:
$ time baz.sh
real 0m4.009s
user 0m0.003s
sys 0m0.000s
Curiosamente, não parece que time
sai assim que o primeiro comando é concluído. Se eu mudar bar.sh
para:
#!/bin/sh
sleep 2
seq 1 5
E, time
novamente, eu esperava que a time
saída fosse impressa antes do seq
mas não é:
$ time ( { foo.sh | bar.sh; } )
1
2
3
4
5
real 0m4.005s
user 0m0.003s
sys 0m0.000s
Parece time
que não conta o tempo que levou para executar, bar.sh
apesar de esperar a conclusão antes de imprimir o relatório 1 .
Todos os testes foram executados em um sistema Arch e usando o bash 4.4.12 (1) - release. Só posso usar o bash para o projeto que faz parte, mesmo que zsh
algum shell poderoso possa contorná-lo, isso não será uma solução viável para mim.
Então, como posso obter o tempo que um conjunto de comandos canalizados levou para executar? E, enquanto estamos nisso, por que não funciona? Parece que time
sai imediatamente assim que o primeiro comando é concluído. Por quê?
Eu sei que posso obter os momentos individuais com algo assim:
( time foo.sh ) 2>foo.time | ( time bar.sh ) 2> bar.time
Mas ainda gostaria de saber se é possível cronometrar a coisa toda como uma única operação.
1 Este não parece ser um problema de buffer, eu tentei executar os scripts com unbuffered
e stdbuf -i0 -o0 -e0
e os números ainda foram impressas antes da time
saída.