Wie kann ich die Zeit mit mehreren Befehlen ausführen UND die Zeitausgabe in eine Datei schreiben?

66

Ich möchte einen timeBefehl ausführen , um die Zeit mehrerer Befehle zu messen.

Was ich machen möchte ist:

  • Messen Sie die Laufzeit von allen zusammen
  • Schreiben Sie die timeAusgabe in eine Datei
  • Schreiben Sie das STDERRaus dem Befehl, den ich zu messen binSTDERR

Was ich NICHT tun möchte, ist

  • Schreiben Sie die mehrere Befehle in einem separaten Skript (warum? Weil all dies ist bereits ein Skript , das ich programmatisch bin zu erzeugen, und die Schaffung von ANOTHER temporäre Skript würde mehr Chaos als ich will)

Was ich bisher versucht habe:

/usr/bin/time --output=outtime -p echo "a"; echo "b";

Funktioniert nicht, timewird nur auf dem ersten ausgeführt.

/usr/bin/time --output=outtime -p ( echo "a"; echo "b"; )

Funktioniert nicht, (ist unerwartetes Token.

/usr/bin/time --output=outtime -p { echo "a"; echo "b"; }

Funktioniert nicht, "keine solche Datei oder Verzeichnis".

/usr/bin/time --output=outtime -p ' echo "a"; echo "b";'

Funktioniert nicht, "keine solche Datei oder Verzeichnis".

time ( echo "a"; echo "b"; ) 2>outtime

Funktioniert nicht, da es alle STDERRin umleitet outtime; Ich möchte nur die timeAusgabe dort.

Und natürlich,

time --output=outime echo "a";

Funktioniert seitdem nicht mehr --output=outime: command not found.

Wie kann ich es tun?

Karel Bílek
quelle

Antworten:

90

Verwenden Sie sh -c 'commands'als Befehl zB:

/usr/bin/time --output=outtime -p sh -c 'echo "a"; echo "b"'
Jim Paris
quelle
2
eine kürzere Version:time -p sh -c 'echo "a"; echo "b"'
Geo
8

Versuche dies:

% (time ( { echas z; echo 2 } 2>&3 ) ) 3>&2 2>timeoutput
zsh: command not found: echas
2
% cat timeoutput                                
( { echas z; echo 2; } 2>&3; )  0.00s user 0.00s system 0% cpu 0.004 total

Erläuterung:

Zuerst müssen wir einen Weg finden, die Ausgabe von umzuleiten time. Da timees sich um eine integrierte Shell handelt, wird die vollständige Befehlszeile als zu messender Befehl verwendet, einschließlich Umleitungen. Somit,

% time whatever 2>timeoutput
whatever 2> timeoutput  0.00s user 0.00s system 0% cpu 0.018 total
% cat timeoutput 
zsh: command not found: whatever

[Anmerkung: Janos 'Kommentar impliziert, dass dies nicht der Fall ist bash.] Wir können die Umleitung der timeAusgabe von erreichen, indem wir timein einer Subshell ausführen und dann die Ausgabe dieser Subshell umleiten.

% (time whatever) 2> timeoutput
% cat timeoutput 
zsh: command not found: whatever
whatever  0.00s user 0.00s system 0% cpu 0.018 total

Jetzt haben wir die Ausgabe von erfolgreich umgeleitet time, aber ihre Ausgabe wird mit der Fehlerausgabe des gemessenen Befehls gemischt. Um die beiden zu trennen, verwenden wir einen zusätzlichen Dateideskriptor.

Auf der "Außenseite" haben wir

% (time ... ) 3>&2 2>timeout

Dies bedeutet: Was auch immer in Dateideskriptor 3 geschrieben ist, wird an derselben Stelle ausgegeben, an der jetzt Dateideskriptor 2 (Standardfehler) ausgegeben wird (das Terminal). Und dann leiten wir Standardfehler in die Datei um timeout.

Jetzt haben wir also: Alles, was in stdout und fd 3 geschrieben ist, wird zum Terminal und alles, was in stderr geschrieben ist, wird in die Datei geschrieben. Was bleibt, ist die Umleitung des Stderr des gemessenen Befehls zu fd 3.

% (time whatever 2>&3) 3>&2 2>timeout

Damit die Zeit mehr als einen Befehl misst, müssen wir sie in einer (anderen!) Unterschale (in Klammern) ausführen. Und um die Fehlerausgabe von allen nach fd 3 umzuleiten, müssen wir sie in geschweiften Klammern gruppieren.

Also, endlich kommen wir zu:

% (time ( { whatever; ls } 2>&3 ) ) 3>&2 2>timeoutput

Das ist es.

angus
quelle
Dies ist ein Syntaxfehler in einer POSIX-Shell. Wahrscheinlich ein Bashismus?
josch
@josch die hier verwendete Shell ist zsh.
Angus
6

Nicht die richtige Antwort, aber sehr auf die Frage bezogen.
Timing-Statistiken für mehrere Programme abrufen. Kombinierte Klammern sind erforderlich. Kommandos mit Semikolon trennen.

time ( command1 ; command2 )
Martin T.
quelle
1
Das ist nett. Verwenden Sie && zwischen den Befehlen time ( command1 && command2 ), falls der erste Befehl fehlschlägt. es wird nicht mit der Ausführung des anderen fortfahren.
Bikashg