Je veux time
une commande qui se compose de deux commandes distinctes avec une sortie de tuyauterie à l'autre. Par exemple, considérez les deux scripts ci-dessous:
$ cat foo.sh
#!/bin/sh
sleep 4
$ cat bar.sh
#!/bin/sh
sleep 2
Maintenant, comment puis-je time
signaler le temps pris par foo.sh | bar.sh
(et oui, je sais que la pipe n'a aucun sens ici, mais ce n'est qu'un exemple)? Cela fonctionne comme prévu si je les exécute séquentiellement dans un sous-shell sans tuyauterie:
$ time ( foo.sh; bar.sh )
real 0m6.020s
user 0m0.010s
sys 0m0.003s
Mais je ne peux pas le faire fonctionner lors de la tuyauterie:
$ 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
J'ai lu une question similaire ( comment exécuter le temps sur plusieurs commandes ET écrire la sortie de temps dans un fichier? ) Et j'ai également essayé l' time
exécutable autonome :
$ /usr/bin/time -p sh -c "foo.sh | bar.sh"
real 4.01
user 0.00
sys 0.00
Cela ne fonctionne même pas si je crée un troisième script qui exécute uniquement le canal:
$ cat baz.sh
#!/bin/sh
foo.sh | bar.sh
Et puis le temps que:
$ time baz.sh
real 0m4.009s
user 0m0.003s
sys 0m0.000s
Fait intéressant, il n'apparaît pas comme s'il time
quitte dès que la première commande est effectuée. Si je change bar.sh
pour:
#!/bin/sh
sleep 2
seq 1 5
Et là time
encore, je m'attendais à ce que la time
sortie soit imprimée avant le seq
mais ce n'est pas le cas:
$ time ( { foo.sh | bar.sh; } )
1
2
3
4
5
real 0m4.005s
user 0m0.003s
sys 0m0.000s
On dirait que time
ne compte pas le temps qu'il a fallu pour exécuter bar.sh
malgré l'attente de sa fin avant d'imprimer son rapport 1 .
Tous les tests ont été exécutés sur un système Arch et en utilisant la version bash 4.4.12 (1). Je ne peux utiliser que bash pour le projet dont il s'agit, donc même si zsh
un autre shell puissant peut le contourner, ce ne sera pas une solution viable pour moi.
Alors, comment puis-je obtenir le temps nécessaire à l'exécution d'un ensemble de commandes dirigées? Et pendant que nous y sommes, pourquoi ça ne marche pas? Il semble que time
la sortie soit immédiate dès que la première commande est terminée. Pourquoi?
Je sais que je peux obtenir les temps individuels avec quelque chose comme ça:
( time foo.sh ) 2>foo.time | ( time bar.sh ) 2> bar.time
Mais je voudrais quand même savoir s'il est possible de chronométrer le tout en une seule opération.
1 Cela ne semble pas être un problème de tampon, j'ai essayé d'exécuter les scripts avec unbuffered
et stdbuf -i0 -o0 -e0
et les chiffres étaient toujours imprimés avant la time
sortie.