time
schreibt an stderr
, so würde man annehmen, dass das Hinzufügen 2>&1
zur Befehlszeile seine Ausgabe an leiten sollte stdout
. Das geht aber nicht:
test@debian:~$ cat file
one two three four
test@debian:~$ time wc file > wc.out 2>&1
real 0m0.022s
user 0m0.000s
sys 0m0.000s
test@debian:~$ cat wc.out
1 4 19 file
Nur mit Klammern funktioniert es:
test@debian:~$ (time wc file) > wc.out 2>&1
test@debian:~$ cat wc.out
1 4 19 file
real 0m0.005s
user 0m0.000s
sys 0m0.000s
Warum werden in diesem Fall Klammern benötigt? Warum wird es nicht time wc
als ein einziger Befehl interpretiert ?
io-redirection
shell-builtin
Wolf-Revo-Katzen
quelle
quelle
time
es sich um das Shell-Schlüsselwort handelt oder/usr/bin/time
. Möglicherweise sind hier mehrere Deskriptorsätze beteiligt (die der Shell und die, die an einentime
Prozess gebunden sind). Und vergessen wir nicht die von der()
Unterschale implizierten . ( Warten auf einen Bash-Spezialisten : p)Antworten:
In
ksh
,bash
undzsh
,time
ist kein Befehl (builtin oder nicht), es ist ein reserviertes Wort in der Sprache wiefor
oderwhile
.Es wird verwendet, um eine Pipeline 1 zeitlich zu bestimmen .
Im:
Sie haben eine spezielle Syntax, die die Shell anweist, diese Pipeline auszuführen:
Und Timing-Statistiken dafür melden.
Im:
Es ist dasselbe, Sie planen den
cmd > output 2> error
Befehl und die Timing-Statistiken beziehen sich immer noch auf den Stderr der Shell.Du brauchst:
Oder:
Damit das stderr der Shell umgeleitet wird,
timing-output
bevor das time-Konstrukt (wieder kein Befehl ) verwendet wird (hier zur Zeitcmd > output 2> error 3>&-
).Sie können dieses
time
Konstrukt auch in einer Subshell ausführen , deren stderr umgeleitet wird:Diese Subshell ist hier jedoch nicht erforderlich. Sie müssen nur stderr zum Zeitpunkt des Aufrufs des
time
Konstrukts umleiten .Die meisten Systeme haben auch einen
time
Befehl. Sie können dieses aufrufen, indem Sie dastime
Schlüsselwort deaktivieren . Alles, was Sie tun müssen, ist, dieses Schlüsselwort in Anführungszeichen zu setzen, da Schlüsselwörter nur als solche erkannt werden, wenn sie wörtlich sind.Beachten Sie jedoch, dass das Format und der Stderr von beiden unterschiedlich sein können
time
undcmd
zusammengeführt werdenerror-and-timing-output
.Außerdem kann der
time
Befehl im Gegensatz zumtime
Konstrukt keine Pipelines oder zusammengesetzten Befehle oder Funktionen oder Shell-Builtins zeitlich festlegen ...Wenn es sich um einen eingebauten Befehl handelt, kann er möglicherweise Funktionsaufrufe oder eingebaute Befehle zeitlich festlegen, jedoch keine Zeitumleitungen, Pipelines oder Verbundbefehle.
1 Beachten Sie, dass
bash
(was als) ein Fehler vorliegt, bei demtime (cmd) 2> file
(aber nichttime cmd | (cmd2) 2> file
zum Beispiel) die Timing-Ausgabe an umgeleitet wirdfile
quelle
time
streiche oft meinen Kopf, um mich daran zu erinnern, dass dies ein Schlüsselwort und keine eingebaute Shell ist.'time'
dem Sie die ausführbare Datei handlicher machen als mit Schreiben/usr/bin/time
(oder sogarcommand time
:-)).\time
.Es gibt keinen Befehl namens
time wc
,time
undwc
wird getrennt Wort in der Schale.Nun, da sind oft zwei separate Programm genannt
time
, die ein Shell - Schlüsselwort ist, ist ein weiterer externer Befehl . In Shells, bei denentime
es sich um ein Shell-Schlüsselwort handelt, verwendetetime wc ...
die Shell bei der Eingabe das Schlüsselworttime
anstelle des externen Zeitdienstprogramms .Wenn die Shell ein
time
Schlüsselwort verwendet, muss der Prozess fork () nicht neu gestartet werden, und der aktuelletime
Standardein- und -fehler werden nicht geändert. Der Weiterleitungsteil in:betrifft
wc
nur.Wenn Sie den zusammengesetzten Befehl verwenden
(list)
:Die Shell wurde
time wc file
in einer Subshell ausgeführt und(time wc file)
galt als einzelner Befehl. Der Umleitungsteil wirkt sich auf die Standardausgabe und den Standardfehler aus, die jetzt sowohltime
als auch enthaltenwc
.Sie können den gleichen Effekt erzielen, ohne die Kosten für das Aufteilen eines neuen Prozesses zu verursachen, indem Sie eine andere Form des Gruppierungsbefehls verwenden
{list;}
:Wenn Sie external verwenden
time
, tritt dieses Problem nicht auf, da es in einem neuen Prozess ausgeführt wurde:quelle
time
und/usr/bin/time
? Werden die ausführbaren Dateien funktional gleich aufgerufen?Weil
time
Sie ausführen, ist bash builtin. Bash verarbeitet es auf so besondere Weise.Wenn Sie echte
time
Binärdateien verwenden, verhält es sich genau so, wie Sie es erwarten:Obwohl die Ausgabe dieser Zeit etwas anders ist:
quelle
time cmd > output
mal dencmd > output
befehl undtime foo | bar
malfoo | bar
.Es ist nicht so,
time
dass die Zeitinformation geschrieben wird. Das Builtin veranlassttime
die Shell, dies zu schreiben, nachdem der Befehl abgeschlossen wurde. Die Umleitung wirkt sich jedoch nur auf den Befehl aus.In diesem
(time ...)
Fall wird die Umleitung auf die gesamte Subshell angewendet.quelle
Da es sich bei time um eine eingebaute Shell handelt, wird in das stderr der Shell und nicht in das stderr des Befehls geschrieben.
Die Verwendung von Klammern zwingt den gesamten Befehl in eine untergeordnete Shell, deren stderr umgeleitet werden kann.
Wenn Sie geschweifte Klammern verwenden, erhalten Sie ein ähnliches Ergebnis, ohne eine Unterschale zu starten
(ja, du brauchst das Semikolon)
quelle