Um herauszufinden, wie lange bestimmte Operationen in einem Bash (v4 +) - Skript dauern, möchte ich die Ausgabe des time
Befehls "separat" analysieren und (letztendlich) in einer Bash - Variablen ( let VARNAME=...
) erfassen .
Jetzt benutze ich time -f '%e' ...
(oder eher command time -f '%e' ...
wegen des eingebauten Bash), aber da ich die Ausgabe des ausgeführten Befehls bereits umleite, bin ich wirklich verloren, wie ich die Ausgabe des time
Befehls erfassen würde . Grundsätzlich besteht hier das Problem darin , die Ausgabe von time
von der Ausgabe der ausgeführten Befehle zu trennen .
Was ich möchte, ist die Funktionalität , die Zeitspanne in Sekunden (Ganzzahlen) zwischen dem Starten eines Befehls und seiner Fertigstellung zu zählen. Es muss nicht das time
Kommando oder das jeweilige eingebaute sein.
Bearbeiten: Angesichts der beiden folgenden nützlichen Antworten wollte ich zwei Klarstellungen hinzufügen.
- Ich möchte die Ausgabe des ausgeführten Befehls nicht wegwerfen, aber es spielt keine Rolle, ob er auf stdout oder stderr endet.
- Ich würde einen direkten Ansatz einem indirekten vorziehen (dh die Ausgabe wird direkt abgefangen und nicht in Zwischendateien gespeichert).
Die date
bisherige Lösung kommt dem nahe, was ich will.
quelle
fork()
,execvp()
undwait3()/wait4()
. Dies ist letztendlich, was Zeit und Freunde tun. Mir ist keine einfache Möglichkeit bekannt, dies in bash / perl zu tun, ohne zu einer Datei oder einem ähnlichen Ansatz umzuleiten.Antworten:
Um die Ausgabe von
time
in eine Variable zu bekommen, verwenden Sie folgendes:Sie können auch nur nach einem Zeittyp fragen, z. B. utime:
Um die Zeit zu erhalten, die Sie auch verwenden können
date +%s.%N
, nehmen Sie sie vor und nach der Ausführung und berechnen Sie den Diff:quelle
DIFF=$((END-START))
Verwendung der arithmetischen Ausdrücke. :) ... Danke für die Antwort. +1.%N
im Binfalse-Code) wünschen, müssen Sie entwederbc
Berechnungen durchführen oder diese verfeinern.time (cmd) 2> something
Umleiten der Zeitsteuerungsausgabe auf zwarfile
funktioniert, jedoch nicht (wie in der Dokumentation angegeben). In anderen Shellstime
ist dies kein Schlüsselwort und kann als Fehler angesehen werden . Ich würde mich nicht darauf verlassen, da es in zukünftigen Versionen von möglicherweise nicht funktioniertbash
.In bash wird die Ausgabe des
time
Konstrukts auf den Standardfehler zurückgesetzt, und Sie können den Standardfehler der betroffenen Pipeline umleiten. Lassen Sie uns also mit einem Befehl starten, der an seinem Ausgang und Fehler streamas schreibt:sh -c 'echo out; echo 1>&2 err'
. Um den Fehlerstrom des Befehls nicht mit der Ausgabe von zu verwechselntime
, können wir den Fehlerstrom des Befehls vorübergehend in einen anderen Dateideskriptor umleiten:Dies schreibt
out
auf fd 1,err
fd 3 und die Zeiten auf fd 2:Es wäre angenehmer,
err
fd 2 und die Zeiten fd 3 zu haben, also tauschen wir sie aus, was umständlich ist, da es keine direkte Möglichkeit gibt, zwei Dateideskriptoren auszutauschen:Dies zeigt, wie Sie die Ausgabe des Befehls nachbearbeiten können. Wenn Sie jedoch sowohl die Ausgabe des Befehls als auch dessen Zeiten erfassen möchten, müssen Sie härter arbeiten. Die Verwendung einer temporären Datei ist eine Lösung. Tatsächlich ist dies die einzige zuverlässige Lösung, wenn Sie sowohl den Standardfehler als auch die Standardausgabe des Befehls erfassen müssen. Ansonsten können Sie die gesamte Ausgabe erfassen und die Tatsache nutzen, dass
time
sie ein vorhersagbares Format hat (wenn Sietime -p
das POSIX-Format oder die bash-spezifischeTIMEFORMAT
Variable verwenden).Wenn Sie sich nur um die Uhrzeit der Wanduhr kümmern, ist das
date
Vorher- Nachher-Laufen eine einfache Lösung (wenn dies aufgrund der zusätzlichen Ladezeit des externen Befehls etwas ungenauer ist).quelle
Mit der Zeit wird die Befehlsausgabe auf stdout und die Zeit auf stderr ausgegeben. Um sie zu trennen, können Sie also Folgendes tun:
Aber jetzt ist die Zeit in einer Datei. Ich glaube nicht, dass Bash stderr direkt in eine Variable einfügen kann. Wenn es Ihnen nichts ausmacht, die Ausgabe des Befehls irgendwo umzuleiten, können Sie Folgendes tun:
Wenn Sie dies tun, wird die Ausgabe des Befehls in
outputfile
und die Ausführungszeit in sein$FOO
.quelle
time
, dass stdout und stderr des ausgeführten Befehls in stdout zusammengeführt werden. Aber generell gibt es keine direkte Methode (also ohne Zwischendatei)? +1.time
führt die Befehlestdout
und nicht zusammenstderr
. Die Art und Weise, wie ich es zeigte, ging davon aus, dass Sie nur die Standardausgabe des Befehls benötigten. Dabash
erst gespeichert wird, was rauskommt,stdout
muss man umleiten. Wenn Sie das stderr Ihres Befehls sicher löschen können: Die Uhrzeit steht immer in der letzten Zeile von stderr. Wenn Sie beide Ausgabestreams Ihres Befehls benötigen, würde ich vorschlagen, sie in ein anderes Skript zu packen.Wenn Sie sich in
bash
(und nicht insh
) befinden und keine Genauigkeit von weniger als einer Sekunde benötigen, können Sie den Aufrufdate
vollständig überspringen und dies tun, ohne zusätzliche Prozesse auszulösen, ohne die kombinierte Ausgabe zu trennen und ohne die Ausgabe zu erfassen und zu analysieren aus beliebigen Befehlen:quelle
Zu diesem Zweck ist es wahrscheinlich besser,
times
(alstime
) zu verwenden, inbash
dem die akkumulierten Benutzer- und Systemzeiten für die Shell und für Prozesse, die von der Shell ausgeführt werden, gedruckt werden. Beispiel:Siehe:
help -m times
für mehr Infos.quelle
Beim Zusammenfassen aller vorherigen Antworten unter OSX
Sie können gerne tun
quelle
Installieren
/bin/time
(zBpacman -S time
)Also statt Fehler beim Versuch
-f
flag:Sie können es tatsächlich verwenden:
Und bekommen Sie, was Sie wollen - Zeit in Variable (Beispiel verwendet
%e
für die real verstrichene Zeit, für andere Optionen überprüfenman time
):quelle
/usr/bin/time
auf vielen Systementime
ist eine in Bash eingebaute Shell (und vermutlich auch andere Shells). Solange sich der Pfad zurtime
ausführbaren Datei in befindetPATH
, können wircommand time
sicherstellen, dass wir den externen Befehl im Gegensatz zum eingebauten ausführen.Gerade als Heads-Up bei der Arbeit mit den obigen Aussagen und vor allem unter Berücksichtigung von Grzegorz 'Antwort. Ich war überrascht, auf meinem Ubuntu 16.04 Xenial-System diese beiden Ergebnisse zu sehen:
Ich habe keine Aliase festgelegt und weiß daher nicht, warum dies geschieht.
quelle
time
ist auch eine eingebaute Shell.command
ausführen, verwenden Sie, wenn Sie sicherstellen möchten, dass Sie den integrierten Befehl ausführen, verwenden Siebuiltin
. Hier gibt es keine Magie. Verwenden Siehelp
diese Option, um die verfügbaren Befehle odertype <command>
den Typ<command>
(z. B. einen eingebauten, externen Befehl, eine Funktion oder einen Alias) zu ermitteln.command
Befehls nicht erkannt . Dadurch wird sichergestellt, dass / usr / bin / time aufgerufen wird. Dies bedeutet, dass die folgenden beiden Aussagen kompatibel sind:$ command time -f %e sleep 4
und$ /usr/bin/time -f %e sleep
Wenn Sie dies versuchen, führt es einen einfachen Befehl mit Argumenten aus, setzt $ real $ user $ sys und behält den Exit-Code bei.
Es werden auch keine Subshells gespalten oder Variablen außer dem echten Benutzersys mit Füßen getreten und die Ausführung des Skripts wird nicht anderweitig gestört
z.B
hinweis: es ist nur mal der einfache befehl keine pipeline, deren komponenten in einer subshell ausgeführt werden
In dieser Version können Sie als $ 1 den Namen der Variablen angeben, die dreimal empfangen werden sollen:
z.B
und kann nützlich sein, wenn es am Ende rekursiv aufgerufen wird, um ein Überfahren der Zeiten zu vermeiden; Aber dann sollte rus etc in ihrer Verwendung als lokal deklariert werden.
http://blog.sam.liddicott.com/2016/01/timeing-bash-commands.html
quelle