780 Stimmen

Wie schreibe ich einen Standardfehler in eine Datei, während ich "tee" mit einer Pipe verwende?

Ich weiß, wie man tee um die Ausgabe zu schreiben ( Standardausgabe ) von aaa.sh a bbb.out und wird dennoch im Terminal angezeigt:

./aaa.sh | tee bbb.out

Wie würde ich jetzt auch schreiben Standardfehler in eine Datei namens ccc.out und trotzdem angezeigt wird?

1057voto

lhunath Punkte 111281

Ich gehe davon aus, dass Sie weiterhin Standardfehler und Standardausgaben auf dem Terminal sehen wollen. Sie könnten sich für Die Antwort von Josh Kelley aber ich finde, dass man einen tail im Hintergrund, die Ihre Protokolldatei sehr hakelig und unübersichtlich ausgibt. Beachten Sie, dass Sie eine zusätzliche Dateideskriptor und danach aufräumen, indem man sie tötet, und das sollte technisch in einem trap '...' EXIT .

Es gibt einen besseren Weg, dies zu tun, und Sie haben ihn bereits entdeckt: tee .

Nur, anstatt es nur für die Standardausgabe zu verwenden, haben Sie ein T-Stück für die Standardausgabe und eines für den Standardfehler. Wie werden Sie dies erreichen? Prozess-Substitution und Datei-Umleitung:

command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)

Lassen Sie uns das aufteilen und erklären:

> >(..)

>(...) (Prozess-Substitution) schafft ein FIFO und lässt tee anhören. Dann verwendet es > (Datei-Umleitung), um die Standardausgabe von command an das FIFO, dass Ihre erste tee hört zu.

Das Gleiche gilt für die zweite:

2> >(tee -a stderr.log >&2)

Wir verwenden wieder die Prozesssubstitution, um eine tee Prozess, der von der Standardeingabe liest und die Daten in stderr.log . tee gibt seine Eingabe zurück auf die Standardausgabe, aber da seine Eingabe unser Standardfehler ist, wollen wir die tee Standardausgabe wieder in unseren Standardfehler. Dann benutzen wir die Datei-Umleitung, um die command Standardfehler des FIFO an den Eingang ( tee der Standardeingabe).

参照 Eingabe und Ausgabe

Die Prozess-Substitution ist eine der wirklich schönen Dinge, die man als Bonus erhält, wenn man Bash als Shell wählt, im Gegensatz zu sh (POSIX oder Bourne).


Unter sh müssen Sie die Dinge manuell erledigen:

out="${TMPDIR:-/tmp}/out.$$" err="${TMPDIR:-/tmp}/err.$$"
mkfifo "$out" "$err"
trap 'rm "$out" "$err"' EXIT
tee -a stdout.log < "$out" &
tee -a stderr.log < "$err" >&2 &
command >"$out" 2>"$err"

1001voto

user542833 Punkte 10634

Einfach:

./aaa.sh 2>&1 | tee -a log

Damit wird der Standardfehler einfach auf die Standardausgabe umgeleitet, so dass tee beide Echos nach Protokoll und auf den Bildschirm. Vielleicht übersehe ich etwas, weil einige der anderen Lösungen scheinen wirklich kompliziert.

Anmerkung: Seit Bash Version 4 können Sie |& als Abkürzung für 2>&1 | :

./aaa.sh |& tee -a log

88voto

Anthony Punkte 897

Dies kann für Leute, die dies über Google finden, nützlich sein. Kommentieren Sie einfach das Beispiel aus, das Sie ausprobieren möchten. Natürlich können Sie die Ausgabedateien auch umbenennen.

#!/bin/bash

STATUSFILE=x.out
LOGFILE=x.log

### All output to screen
### Do nothing, this is the default

### All Output to one file, nothing to the screen
#exec > ${LOGFILE} 2>&1

### All output to one file and all output to the screen
#exec > >(tee ${LOGFILE}) 2>&1

### All output to one file, STDOUT to the screen
#exec > >(tee -a ${LOGFILE}) 2> >(tee -a ${LOGFILE} >/dev/null)

### All output to one file, STDERR to the screen
### Note you need both of these lines for this to work
#exec 3>&1
#exec > >(tee -a ${LOGFILE} >/dev/null) 2> >(tee -a ${LOGFILE} >&3)

### STDOUT to STATUSFILE, stderr to LOGFILE, nothing to the screen
#exec > ${STATUSFILE} 2>${LOGFILE}

### STDOUT to STATUSFILE, stderr to LOGFILE and all output to the screen
#exec > >(tee ${STATUSFILE}) 2> >(tee ${LOGFILE} >&2)

### STDOUT to STATUSFILE and screen, STDERR to LOGFILE
#exec > >(tee ${STATUSFILE}) 2>${LOGFILE}

### STDOUT to STATUSFILE, STDERR to LOGFILE and screen
#exec > ${STATUSFILE} 2> >(tee ${LOGFILE} >&2)

echo "This is a test"
ls -l sdgshgswogswghthb_this_file_will_not_exist_so_we_get_output_to_stderr_aronkjegralhfaff
ls -l ${0}

25voto

Josh Kelley Punkte 52169

Um den Standardfehler in eine Datei umzuleiten, die Standardausgabe auf dem Bildschirm anzuzeigen und die Standardausgabe in einer Datei zu speichern:

./aaa.sh 2>ccc.out | tee ./bbb.out

Um sowohl den Standardfehler als auch die Standardausgabe auf dem Bildschirm anzuzeigen und beide in einer Datei zu speichern, können Sie die Bash-Funktion E/A-Umleitung :

#!/bin/bash

# Create a new file descriptor 4, pointed at the file
# which will receive standard error.
exec 4<>ccc.out

# Also print the contents of this file to screen.
tail -f ccc.out &

# Run the command; tee standard output as normal, and send standard error
# to our file descriptor 4.
./aaa.sh 2>&4 | tee bbb.out

# Clean up: Close file descriptor 4 and kill tail -f.
exec 4>&-
kill %1

25voto

Mit anderen Worten, Sie wollen stdout in einen Filter leiten ( tee bbb.out ) und stderr in einen anderen Filter ( tee ccc.out ). Es gibt keine Standardmethode, um etwas anderes als stdout in einen anderen Befehl zu leiten, aber Sie können das umgehen, indem Sie mit Dateideskriptoren jonglieren.

{ { ./aaa.sh | tee bbb.out; } 2>&1 1>&3 | tee ccc.out; } 3>&1 1>&2

Siehe auch Wie kann man den Standardfehlerstrom (stderr) auslesen? y Wann würden Sie einen zusätzlichen Dateideskriptor verwenden?

In bash (und ksh und zsh), aber nicht in anderen POSIX-Shells wie dash, können Sie Prozesssubstitution :

./aaa.sh > >(tee bbb.out) 2> >(tee ccc.out)

Beachten Sie, dass dieser Befehl in der Bash zurückkehrt, sobald ./aaa.sh beendet, auch wenn die tee Befehle werden weiterhin ausgeführt (ksh und zsh warten auf die Unterprozesse). Dies kann ein Problem sein, wenn Sie etwas tun wie ./aaa.sh > >(tee bbb.out) 2> >(tee ccc.out); process_logs bbb.out ccc.out . Verwenden Sie in diesem Fall stattdessen Dateideskriptor-Jonglierung oder ksh/zsh.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X