Leiten Sie die Ausgabe eines Befehls in "Zeitbefehl" um

10

Ich versuche, etwas zeitlich zu bestimmen, indem ich:

/usr/bin/time myCommand

Da jedoch /usr/bin/timein stderr geschrieben wird und myCommand auch in stderr schreibt, wird mehr als nur die Zeit im Stream ausgegeben. Was ich tun möchte, ist, die gesamte Ausgabe von myCommand an umzuleiten /dev/null, aber trotzdem die Ausgabe der Zeit an stderr zu schreiben. Anhand eines Beispiels myCommand , das in stderr von schreibt ls /nofile, sehen wir, dass (offensichtlich) überhaupt keine Ausgabe mit folgendem Ergebnis erfolgt :

$ /usr/bin/time ls /nofile 2> /dev/null
$

Ohne Umleitung sehen wir sowohl die Ausgabe von ls(nach stderr) als auch die Ausgabe von time (auch nach stderr):

$ /usr/bin/time ls /nofile
ls: cannot access /nofile: No such file or directory
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

Was ich will, ist etwas, das einfach produziert:

$ /usr/bin/time ls /nofile > RedirectThatImAskingFor
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 3776maxresident)k
0inputs+0outputs (0major+278minor)pagefaults 0swaps

Irgendwelche Ideen?

David Doria
quelle
Ich verwende den Befehl time in der Skriptdatei. Ich möchte eine Zeitausgabe in stdout anstelle von stderr. Wie kann ich das bekommen?
Verwandte: stackoverflow.com/questions/13356628/…
Ciro Santilli 4 病毒 审查 六四 六四 4

Antworten:

20

In ksh ist bash und zsh timeein Schlüsselwort, kein eingebautes. Umleitungen in derselben Zeile gelten nur für den zeitgesteuerten Befehl, nicht für die Ausgabe von sich timeselbst.

$ time ls -d / /nofile >/dev/null 2>/dev/null

real    0m0.003s
user    0m0.000s
sys     0m0.000s

Um die Ausgabe von sich timeselbst in diesen Shells umzuleiten , müssen Sie eine zusätzliche Gruppierungsebene verwenden.

{ time mycommand 2>&3; } 3>&2 2>mycommand.time

Wenn Sie die GNU-Version des eigenständigen timeDienstprogramms verwenden, können Sie -odie Ausgabe an einer timeanderen Stelle als stderr schreiben . Sie können timein das Terminal schreiben:

/usr/bin/time -o /dev/tty mycommand >/dev/null 2>/dev/null

Wenn Sie die Ausgabe timeauf ihren Standardfehler beschränken möchten , benötigen Sie eine zusätzliche Ebene für das Mischen von Dateideskriptoren.

/usr/bin/time -o /dev/fd/3 mycommand 3>&2 >/dev/null 2>/dev/null

Mit jedem timeDienstprogramm können Sie eine Zwischenshell aufrufen, um die gewünschten Umleitungen auszuführen. Das Aufrufen einer Zwischen-Shell, um zusätzliche Aktionen wie cdUmleitungen usw. auszuführen , ist ziemlich häufig - es sind die kleinen Dinge, für die Shells entwickelt wurden.

/usr/bin/time sh -c 'exec mycommand >/dev/null 2>/dev/null'
Gilles 'SO - hör auf böse zu sein'
quelle
Ein paar Folgemaßnahmen: 1) Was macht der 'exec' in Ihrem letzten Vorschlag? Es scheint ohne es zu funktionieren: / usr / bin / time sh -c 'exec ls / nofile &> ./ output.dat' 2) Ist eine "Zwischenschale" die gleiche wie eine "Unterschale" (die Sie mir geben würden) Denken Sie mit Klammern?). Ich hatte Dinge wie / usr / bin / time (ls / nofile &> ./ output.dat) ohne Erfolg ausprobiert. 3) Was ist / dev / tty? Ich weiß, dass tty0 stdin ist, tty1 = stdout, tty2 = stderr, aber was ist mit 'tty'?
David Doria
4) Mit der Option / dev / fd3 scheinen Sie die Ausgabe -o auf 3 zu schreiben und dann 3 auf 2, 1 auf null und 2 auf null umzuleiten. Sollte das nicht auch 3 nach null senden, da die Umleitungen von links nach rechts erfolgen?
David Doria
1
@DavidDoria execersetzt die Shell durch das angegebene Programm, anstatt dieses Programm als Unterprozess auszuführen . Einige Shells führen diese Optimierung automatisch durch, wenn ein Befehl der letzte in einem Skript ist. "Intermediate Shell" bedeutet genau das: eine Shell, die zwischen timeund liegt mycommand; es hat nichts mit Unterschalen zu tun. /dev/ttyist das Terminal, auf dem der Befehl ausgeführt wird (es hat nichts mit /dev/ttyNUMphysischen Konsolen zu tun; Sie verwechseln die Dateideskriptoren: stdin is /dev/fd/0usw.).
Gilles 'SO - hör auf böse zu sein'
@DavidDoria Das Ändern der Verbindung eines Dateideskriptors erfolgt von links nach rechts, was den gegenteiligen Effekt hat. Siehe unix.stackexchange.com/questions/23964/… oder unix.stackexchange.com/questions/37660/order-of-redirections
Gilles 'SO- hör auf böse zu sein
0
[artur@asus-ux21e ~]$ find /etc/pki/CA/private/
/etc/pki/CA/private/
find: ‘/etc/pki/CA/private/’: Permission denied
[artur@asus-ux21e ~]$ time (find /etc/pki/CA/private/ &> /dev/null)

real    0m0.006s
user    0m0.001s
sys 0m0.004s
Artur Szymczak
quelle
Das ist nicht die gleiche "Zeit" (es ist ein Bash-Alias, glaube ich). Beachten Sie, dass es keinen vernünftigen Umleitungsregeln folgt? $ time &> / dev / null real 0m0.000s Benutzer 0m0.000s sys 0m0.000s
David Doria
1
Wie wäre es damit: / usr / bin / time -o time / usr / bin / find / etc / pki / CA / privat / &> / dev / null; Katzenzeit
Artur Szymczak
Ja, ich habe das gesehen, aber ich war eher neugierig, wie es geht, ohne einen internen Mechanismus wie -o zu verwenden.
David Doria
@DavidDoria Was gibt Ihnen den Eindruck, dass timees sich um einen Bash-Alias ​​handelt? which timewird /usr/bin/timein CentOS 5.7 angezeigt .
Timothy Martin
type timewird Ihnen zeigen:time is a shell keyword
Artur Szymczak