Wie leite ich die Ausgabe des Befehls time in eine Datei unter Linux um?

201

Nur eine kleine Frage zu Timing-Programmen unter Linux: Mit dem Befehl time kann die Ausführungszeit eines Programms gemessen werden:

[ed@lbox200 ~]$ time sleep 1

real    0m1.004s
user    0m0.000s
sys     0m0.004s

Welches funktioniert gut. Wenn ich jedoch versuche, die Ausgabe in eine Datei umzuleiten, schlägt dies fehl.

[ed@lbox200 ~]$ time sleep 1 > time.txt

real    0m1.004s
user    0m0.001s
sys     0m0.004s

[ed@lbox200 ~]$ cat time.txt 
[ed@lbox200 ~]$ 

Ich weiß, dass es andere Zeitimplementierungen mit der Option -o gibt, um eine Datei zu schreiben, aber meine Frage betrifft den Befehl ohne diese Optionen.

Irgendwelche Vorschläge ?

ed82
quelle
3
Mögliches Duplikat der Bash-Skript-Schreibausführungszeit in einer Datei , und ich bin weit davon entfernt, davon überzeugt zu sein, dass dies die erste derartige Frage ist.
Jonathan Leffler
1
Dies ist ein Duplikat von stackoverflow.com/questions/2408981/…
Codeforester

Antworten:

265

Versuchen

{ time sleep 1 ; } 2> time.txt

Dies kombiniert den STDERR von "Zeit" und Ihren Befehl in time.txt

Oder verwenden

{ time sleep 1 2> sleep.stderr ; } 2> time.txt

Dadurch wird STDERR aus "sleep" in die Datei "sleep.stderr" eingefügt, und nur STDERR aus "time" wird in "time.txt" gespeichert.

Januar
quelle
2
Danke, das beantwortet genau meine Frage. Wenn ich es richtig verstanden habe, kann das Ergebnis des Zeitbefehls von stderr?
ed82
7
Ja, aber Sie müssen es in geschweifte Klammern setzen, sonst ist die Umleitung Teil des Befehls, der timeausgewertet wird.
Januar
5
@Daniel Sie können die interne Befehlsausgabe immer separat umleiten (dh {time sleep 1 2> sleepStdErr.txt;} 2> time.txt), und dadurch erhalten Sie nur die Zeitausgabe. Ich bin mir nicht sicher, ob es einen Weg gibt, es sonst unabhängig zu bekommen.
gms7777
10
Wenn Sie Zeit mit etwas wie grep verwenden möchten, das von stdout liest, versuchen Sie es { time sleep 1; } 2>&1 | grep real. Dies sendet stderr an stdout, das grep dann lesen kann.
Clayzermk1
9
vergiss NICHT das ';' Zeichen vor dem Schließen von '}', es wird NICHT ohne funktionieren (ich habe es getan und ... frage mich, warum es nicht funktioniert :))
THESorcerer
37

Wrap timeund der Befehl, den Sie steuern, in Klammern.

Zum Beispiel die folgenden Zeiten lsund schreibt das Ergebnis lsund die Ergebnisse des Timings in outfile:

$ (time ls) > outfile 2>&1

Oder wenn Sie die Ausgabe des Befehls von der erfassten Ausgabe trennen möchten von time:

$ (time ls) > ls_results 2> time_results
Sampson-Chen
quelle
12
Es ist nicht notwendig, hier eine Unterschale einzuführen.
Januar
1
@ sampson-chen Das funktioniert nur, weil ls nichts an stderr schreibt, oder? Wie würden Sie die Ausgabe von 'Zeit' von der des auszuführenden Befehls "trennen", wenn der Befehl sowohl in stdout als auch in stderr schreibt?
David Doria
36

Einfach. Das GNU- timeDienstprogramm hat dafür eine Option.

Sie müssen jedoch sicherstellen, dass Sie den integrierten Befehl Ihrer Shell nicht verwenden. timeZumindest bashbietet der integrierte Befehl diese Option nicht! Aus diesem Grund müssen Sie den vollständigen Pfad des timeDienstprogramms angeben:

/usr/bin/time -o time.txt sleep 1
cmaster - Monica wieder einsetzen
quelle
Sie können das nicht eingebaute auch verwenden, ohne den vollständigen Pfad anzugeben: stackoverflow.com/questions/29540540/…
Ciro Santilli 18 冠状 病 六四 事件 4
14

Wenn Sie sich für die Fehlerausgabe des Befehls interessieren, können Sie diese auf diese Weise trennen, während Sie weiterhin den integrierten Zeitbefehl verwenden.

{ time your_command 2> command.err ; } 2> time.log

oder

{ time your_command 2>1 ; } 2> time.log

Wie Sie sehen, gehen die Fehler des Befehls in eine Datei (da stderrwird für verwendet time).

Leider können Sie es nicht an ein anderes Handle (wie 3>&2) senden, da es außerhalb des Handles nicht mehr existiert{...}

Das heißt, wenn Sie die GNU-Zeit nutzen können, tun Sie einfach, was @Tim Ludwinski gesagt hat.

\time -o time.log command
Kennzeichen
quelle
8

Da die Ausgabe des Befehls 'time' eine Fehlerausgabe ist, wäre eine Umleitung als Standardausgabe für die weitere Verarbeitung intuitiver.

{ time sleep 1; } 2>&1 |  cat > time.txt
jaycee xu
quelle
6

Wenn Sie die GNU-Zeit anstelle der integrierten Bash verwenden, versuchen Sie es

time -o outfile command

(Hinweis: Die GNU-Zeitformate unterscheiden sich geringfügig von der integrierten Bash-Zeit.)

Tim Ludwinski
quelle
1
Das danke. Und Sie können verwendet werden \time -o outfile command(mit ``) zur Verwendung GNU statt eingebaut.
Mark
3
&>out time command >/dev/null

in deinem Fall

&>out time sleep 1 >/dev/null

dann

cat out
Alinsoar
quelle
3
Elegante Idee, führt aber dazu, dass die Shell ihren eingebauten Befehl nicht verwendet. Wenn Sie keine echte timeBinärdatei installiert haben, outwird so etwas enthalten bash: time: command not found.
scy
Außerdem stimmt das Format für die GNU-Zeit nicht mit dem eingebauten Bash überein, was zu Problemen beim automatischen Parsen führt.
Guss
3

Am Ende habe ich verwendet:

/usr/bin/time -ao output_file.txt -f "Operation took: %E" echo lol
  • Wo "a" angehängt ist
  • Wobei "o" mit dem Dateinamen fortfährt, an den angehängt werden soll
  • Wobei "f" ein Format mit einer printf-ähnlichen Syntax ist
  • Wobei "% E" 0:00:00 erzeugt; Stunden: Minuten: Sekunden
  • Ich musste / usr / bin / time aufrufen, weil die Bash "time" es mit Füßen getreten hat und nicht die gleichen Optionen hat
  • Ich habe nur versucht, die Ausgabe in eine Datei zu bringen, nicht das Gleiche wie OP
Locane
quelle
2
#!/bin/bash

set -e

_onexit() {
    [[ $TMPD ]] && rm -rf "$TMPD"
}

TMPD="$(mktemp -d)"
trap _onexit EXIT

_time_2() {
    "$@" 2>&3
}

_time_1() {
    time _time_2 "$@"
}

_time() {
    declare time_label="$1"
    shift
    exec 3>&2
    _time_1 "$@" 2>"$TMPD/timing.$time_label"
    echo "time[$time_label]"
    cat "$TMPD/timing.$time_label"
}

_time a _do_something
_time b _do_another_thing
_time c _finish_up

Dies hat den Vorteil, dass keine Sub-Shells erzeugt werden, und bei der endgültigen Pipeline wird der Stderr auf den tatsächlichen Stderr zurückgesetzt.

Adam Heath
quelle
0

Wenn Sie stdout und stderr des ursprünglichen Prozesses nicht berühren möchten, können Sie stderr zu Dateideskriptor 3 und zurück umleiten:

$ { time { perl -le "print 'foo'; warn 'bar';" 2>&3; }; } 3>&2 2> time.out
foo
bar at -e line 1.
$ cat time.out

real    0m0.009s
user    0m0.004s
sys     0m0.000s

Sie können dies für einen Wrapper (z. B. für Cronjobs) verwenden, um die Laufzeiten zu überwachen:

#!/bin/bash

echo "[$(date)]" "$@" >> /my/runtime.log

{ time { "$@" 2>&3; }; } 3>&2 2>> /my/runtime.log
Tobias Gödderz
quelle
0

Wenn Sie verwenden csh, können Sie verwenden:

/usr/bin/time --output=outfile -p $SHELL  -c 'your command'

Beispielsweise:

/usr/bin/time --output=outtime.txt -p csh -c 'cat file'
Leo Cardona
quelle