Ich möchte time
einen 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 time
nun die Zeit foo.sh | bar.sh
abrufen, 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 time
ausfü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 time
aus, als würde es beendet, sobald der erste Befehl ausgeführt wird. Wenn ich bar.sh
zu:
#!/bin/sh
sleep 2
seq 1 5
Und time
andererseits hatte ich erwartet, dass die time
Ausgabe vor dem gedruckt wird, seq
aber es ist nicht:
$ time ( { foo.sh | bar.sh; } )
1
2
3
4
5
real 0m4.005s
user 0m0.003s
sys 0m0.000s
Sieht time
so aus, als würde die Ausführungszeit nicht gezählt, bar.sh
obwohl 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 zsh
eine 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 time
aus, 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 unbuffered
und auszuführen, stdbuf -i0 -o0 -e0
und die Zahlen wurden vor der time
Ausgabe noch gedruckt .