Ich möchte timeeinen Befehl, der aus zwei separaten Befehlen besteht, mit einem Piping-Ausgang zu einem anderen. Betrachten Sie beispielsweise die beiden folgenden Skripte:
$ cat foo.sh
#!/bin/sh
sleep 4
$ cat bar.sh
#!/bin/sh
sleep 2
Wie kann ich timenun die Zeit foo.sh | bar.shabrufen, die vergangen ist (und ja, ich weiß, dass die Pipe hier keinen Sinn ergibt, aber dies ist nur ein Beispiel)? Es funktioniert wie erwartet, wenn ich sie nacheinander in einer Subshell ohne Piping ausführe:
$ time ( foo.sh; bar.sh )
real 0m6.020s
user 0m0.010s
sys 0m0.003s
Aber ich kann es nicht zum Laufen bringen:
$ 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
Ich habe eine ähnliche Frage durchgelesen ( wie man Zeit mit mehreren Befehlen ausführt UND die Zeitausgabe in eine Datei schreibt? ) Und auch die eigenständige timeausführbare Datei ausprobiert :
$ /usr/bin/time -p sh -c "foo.sh | bar.sh"
real 4.01
user 0.00
sys 0.00
Es funktioniert nicht einmal, wenn ich ein drittes Skript erstelle, das nur die Pipe ausführt:
$ cat baz.sh
#!/bin/sh
foo.sh | bar.sh
Und dann mal das:
$ time baz.sh
real 0m4.009s
user 0m0.003s
sys 0m0.000s
Interessanterweise sieht es nicht so timeaus, als würde es beendet, sobald der erste Befehl ausgeführt wird. Wenn ich bar.shzu:
#!/bin/sh
sleep 2
seq 1 5
Und timeandererseits hatte ich erwartet, dass die timeAusgabe vor dem gedruckt wird, seqaber es ist nicht:
$ time ( { foo.sh | bar.sh; } )
1
2
3
4
5
real 0m4.005s
user 0m0.003s
sys 0m0.000s
Sieht timeso aus, als würde die Ausführungszeit nicht gezählt, bar.shobwohl gewartet wurde, bis der Bericht gedruckt wurde 1 .
Alle Tests wurden auf einem Arch-System und mit bash 4.4.12 (1) -release durchgeführt. Ich kann bash nur für das Projekt verwenden. Dies ist ein Teil davon. Selbst wenn zsheine andere leistungsstarke Shell es umgehen kann, ist dies für mich keine praktikable Lösung.
Wie kann ich also die Zeit ermitteln, die eine Reihe von Pipe-Befehlen für die Ausführung benötigt hat? Und wenn wir schon dabei sind, warum funktioniert es dann nicht? Es sieht so timeaus, als würde es sofort beendet, sobald der erste Befehl beendet ist. Warum?
Ich weiß, ich kann die einzelnen Zeiten mit so etwas abrufen:
( time foo.sh ) 2>foo.time | ( time bar.sh ) 2> bar.time
Aber ich würde immer noch gerne wissen, ob es möglich ist, das Ganze als einzelne Operation zu messen.
1 Dies scheint kein Pufferproblem zu sein. Ich habe versucht, die Skripte mit unbufferedund auszuführen, stdbuf -i0 -o0 -e0und die Zahlen wurden vor der timeAusgabe noch gedruckt .