Warum geht die Ausgabe einiger Linux-Programme weder nach STDOUT noch nach STDERR?
Eigentlich möchte ich wissen, wie man zuverlässig die gesamte Programmausgabe erfasst, egal welchen "Stream" er verwendet. Das Problem, das ich habe, ist, dass einige Programme ihre Ausgabe nicht erfassen zu lassen scheinen.
Ein Beispiel ist der Befehl 'time':
time sleep 1 2>&1 > /dev/null
real 0m1.003s
user 0m0.000s
sys 0m0.000s
oder
time sleep 1 &> /dev/null
real 0m1.003s
user 0m0.000s
sys 0m0.000s
Warum wird die Ausgabe beide Male angezeigt? Ich habe erwartet, dass alles nach / dev / null geleitet wird .
Welchen Ausgabestream verwendet die Zeit und wie kann ich ihn in eine Datei leiten?
Eine Möglichkeit, das Problem zu umgehen , besteht darin, ein Bash- Skript zu erstellen , das beispielsweise den folgenden combine.sh
Befehl enthält:
$@ 2>&1
Dann kann die Ausgabe von 'time' auf die richtige Weise erfasst werden:
combine.sh time sleep 1 &> /dev/null
(keine Ausgabe wird gesehen - richtig)
Gibt es eine Möglichkeit, das zu erreichen, was ich möchte, ohne ein separates Kombinationsskript zu verwenden?
2>&1 > /dev/null
Mittel „2 geht nun an , wo 1 geht (dh das Terminal, in der Standardeinstellung), und dann 1 jetzt geht an / dev / null (aber 2 geht noch zum Terminal!) verwenden.>/dev/null 2>&1
sagen "1 geht jetzt nach / dev / null, dann geht 2 dorthin, wo 1 geht (dh auch nach / dev / null). Dies funktioniert hier immer noch nicht, da die eingebaute 'Zeit' nicht umgeleitet wird, aber im Allgemeinen korrekt ist (zum Beispiel würde es funktionieren, wenn Sie / usr / bin / time verwenden). Stellen Sie sich "2> & 1" vor, als würde die "Richtung" von 1 in 2 kopiert, nicht als "Gehe zu 1"Antworten:
Diese Frage wird in BashFAQ / 032 angesprochen . In Ihrem Beispiel würden Sie:
Der Grund warum
nicht verhalten , wie Sie erwarten, weil mit dieser Syntax, die Sie wollen , werden
time
den Befehlsleep 1 2>/dev/null
(ja, der Befehlsleep 1
mit stderr umgeleitet/dev/null
). Das Builtintime
funktioniert so, dass dies tatsächlich möglich ist.Der
bash
Builtin kann dies tatsächlich tun, weil ... nun, es ist ein Builtin. Ein solches Verhalten wäre mit dem externen Befehl, der sichtime
normalerweise in befindet, unmöglich/usr/bin
. Tatsächlich:Nun die Antwort auf Ihre Frage
Ist dies der Fall, geht die Ausgabe zu stdout oder stderr .
Hoffe das hilft!
quelle
exec 3>/some/file ; ls >&3 ;
)coproc
eingebauten. Beimtime
eingebauten ist dies jedoch nicht der Fall .Ihre spezielle Frage zu
time
builtin wurde beantwortet, aber es gibt einige Befehle, die weder nachstdout
noch nach schreibenstderr
. Ein klassisches Beispiel ist der Unix-Befehlcrypt
.crypt
Ohne Argumente werden Standardeingaben verschlüsseltstdin
und in die Standardausgabe geschriebenstdout
. Es fordert den Benutzer zur Eingabe eines Kennworts aufgetpass()
, das standardmäßig eine Eingabeaufforderung für ausgibt/dev/tty
./dev/tty
ist das aktuelle Endgerät. Schreiben auf/dev/tty
bewirkt, dass in das aktuelle Terminal geschrieben wird (falls vorhanden, sieheisatty()
).Der Grund, warum
crypt
nicht in geschrieben werden kann,stdout
ist, dass verschlüsselte Ausgaben in geschrieben werdenstdout
. Es ist auch besser, aufzufordern,/dev/tty
anstatt zu schreiben,stderr
damit die Aufforderung weiterhin angezeigt wird , wenn ein Benutzer aufstdout
und umleitetstderr
. (Aus dem gleichen Grundcrypt
kann das Kennwort nicht gelesen werdenstdin
, da es zum Lesen der zu verschlüsselnden Daten verwendet wird.)quelle
time sleep 1 > /dev/null 2>&1
# leitet die Ausgabe von "sleep" um do null. Dann schreibt "time" seine eigene Ausgabe ohne Umleitung. Es ist wie "time (sleep 1 > /dev/null 2>&1)
".(time sleep 1) > /dev/null 2>&1
# führt "Zeitschlaf 1" aus und leitet dann seine Ausgabe auf null um.[] s
quelle
Das Problem in Ihrem Fall ist, dass die Umleitung auf andere Weise funktioniert. Sie schrieben
Dadurch wird die Standardausgabe an
/dev/null
und der Standardfehler an die Standardausgabe weitergeleitet.Um alle Ausgaben umzuleiten, müssen Sie schreiben
Dann wird der Standardfehler zur Standardausgabe umgeleitet, und danach wird die gesamte Standardausgabe (die den Standardfehler enthält) zu umgeleitet
/dev/null
.quelle
time
. Siehe meine Antwort für einige Erklärungen.