Frage Wie man stderr leitet, ohne zu stopfen


Wie kann ich den Standardfehler-Stream pipen, ohne den Standard-Out-Stream zu pipen?

Ich weiß, dass dieser Befehl funktioniert, schreibt aber auch den Standard heraus.

Command 2>&1 | tee -a $LOG

Wie bekomme ich nur den Standardfehler?

Hinweis: Ich möchte nur den stderr-Stream in ein Protokoll schreiben und sowohl stderr als auch stdout in die Konsole schreiben.


23
2017-09-09 12:48


Ursprung




Antworten:


Verwenden Sie dazu einen zusätzlichen Dateideskriptor, um stderr und stdout zu ändern:

find /var/log 3>&1 1>&2 2>&3 | tee foo.file

Grundsätzlich funktioniert es, oder zumindest ich denke es funktioniert, wie folgt:
Die Umleitungen werden von links nach rechts ausgewertet.

3>&1 Erstellt einen neuen Dateideskriptor, 3 ein Duplikat (Kopie) von fd 1 (stdout).

1>&2 Machen Sie stdout (1) ein Duplikat von fd 2 (stderr)

2>&3 Machen Sie fd 2, ein Duplikat (Kopie) von 3, das zuvor eine Kopie von stdout gemacht wurde.

Jetzt sind also stderr und stdout geschaltet.

| tee foo.file tee dupliziert den Dateideskriptor 1, der in stderr erstellt wurde.


24
2017-09-09 12:55



Oh, nicht mit ksh getestet, funktioniert aber mit Bash ... - Kyle Brandt♦
Danke, arbeitet auch in ksh. Ich denke die meisten der Pipe und Stream Dinge sind Posix Standard. - C. Ross
"Kopie" ist nicht wirklich korrekt - Siehe @ Guasqueños Antwort. - Kyle Brandt♦
Dies funktioniert auch in Windows mit tee.exe Eingerichtet :) - Acorn


Kyles Unix / Linux-Kommando erledigt die Aufgabe, den STDERR mit dem STDOUT zu wechseln; Die Erklärung ist jedoch nicht ganz richtig. Die Umleitungsoperatoren kopieren und duplizieren nicht, sie leiten den Fluss nur in eine andere Richtung um.

Das Umschreiben von Kyles Befehl durch vorübergehendes Verschieben der 3> & 1 zum Ende würde das Verständnis des Konzepts erleichtern:

find /var/log  1>&2  2>&3  3>&1  

Auf diese Weise würde Linux einen Fehler anzeigen, da & 3 noch nicht existiert, da es sich vor 3> & 1 befindet. 3> etwas ist eine Möglichkeit zu erklären (definieren), dass wir ein drittes Rohr verwenden werden, also muss es lokalisiert werden, bevor wir Wasser in dieses Rohr fließen lassen, zum Beispiel die Art, wie Kyle es geschrieben hat. Probieren Sie diese andere Möglichkeit nur zum Spaß aus:

((echo "STD1";  anyerror "bbbb"; echo "STD2" ) 3>&1 4>&2 1>&4 2>&3) > newSTDOUT 2> newSTDERR

Es ist eine Schande, keine Kopien zu haben. Sie können Dinge wie "3> & 1 3> & 2" nicht im selben Befehl ausführen, da Linux nur den ersten gefundenen und den zweiten ignoriert.

Ich habe (noch) keine Möglichkeit gefunden, sowohl den Fehler als auch die reguläre Ausgabe in eine Datei zu senden und eine Kopie des Fehlers mit einem Befehl an die Standardausgabe zu senden. Zum Beispiel habe ich einen Cron-Job, bei dem ich möchte, dass beide Ausgaben (Fehler und Standard) in eine Log-Datei gehen und der Fehler auch ausgeht, um eine E-Mail-Nachricht an meine Blackberry zu senden. Ich kann es mit zwei Befehlen mit "Tee" tun, aber der Fehler wird nicht in der richtigen Reihenfolge zwischen der regulären Ausgabezeile in der Datei angezeigt. Das ist die hässliche Art, wie ich das Problem gelöst habe:

((echo "STD1"; sdfr "bbbb"; echo "STD2" ) 3>&1 1>&2 2>&3 | tee -a log1 ) 2>> log1

Beachten Sie, dass ich log1 zweimal verwenden muss und dass ich in beiden Fällen anhängen muss, die ersten mit der Option "-a" für den Befehl "tee" und die zweite mit ">>".

Machen a Katze log1 Du bekommst folgendes:

STD1
STD2
-bash: sdfr: command not found

Beachten Sie, dass der Fehler nicht wie erwartet in der zweiten Zeile angezeigt wird.


12
2017-11-19 18:47



Genial Korrektur! - Kyle Brandt♦
Schau Dir zsh und mult_ios Möglichkeit (standardmäßig aktiviert), um eine FD mehrfach umzuleiten. - Tom Hale


Nach der Manpage für ksh (pdksh) kannst du einfach tun:

Befehl 2> & 1> / dev / null | Katze -n

dup stderr nach stdout, stdout nach / dev / null umleiten, dann in 'cat -n' pipen

funktioniert auf pdksh auf meinem System:

$ errorecho () {echo "$ @"> & 2;}

$ errorecho foo
foo

$ errorecho foo> / dev / null # sollte immer noch angezeigt werden, obwohl stdout umgeleitet wurde
foo

$ errorecho foo 2> & 1> / dev / null | Katze -n
     1 foo
$

2
2017-09-09 21:46



Funktioniert auch mit BusyBox - Udo G


Ich habe es so laufen lassen, wie du es immer wolltest, da ich es auch gebraucht habe und deinen Befehl verfeinert habe. jetzt für mich funktioniert es richtig mit Bash 3.2 auf Debian Squeeze mit diesem

(echo "foo" 3>&1 1>&2 2>&3 | tee -a log1 ) 2>> log1 >> log2

während log1 stdout und stderr protokolliert und log2 nur stderr protokolliert und nichts anderes auf den Bildschirm legt.


1
2018-02-12 15:23