Ich gehe davon aus, dass Sie STDERR und STDOUT weiterhin auf dem Terminal sehen möchten. Sie könnten sich für Josh Kelleys Antwort entscheiden, aber ich finde, dass Sie einen tail
behalten herum im Hintergrund, der Ihre Protokolldatei sehr hackish und klobig ausgibt. Beachten Sie, wie Sie einen Exra-FD behalten und danach aufräumen müssen, indem Sie ihn töten, und das sollte technisch gesehen in einem trap '...' EXIT
geschehen .
Es gibt einen besseren Weg, dies zu tun, und Sie haben ihn bereits entdeckt:tee
.
Nur, anstatt es nur für Ihre stdout zu verwenden, haben Sie ein T-Stück für stdout und eines für stderr. Wie werden Sie dies erreichen? Prozesssubstitution und Dateiumleitung:
command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
Teilen wir es auf und erklären es:
> >(..)
>(...)
(Process Substitution) erstellt einen FIFO und lässt tee
hör drauf. Dann verwendet es >
(Dateiumleitung), um die STDOUT von command
umzuleiten zum FIFO, dass Ihre erste tee
hört zu.
Dasselbe für die zweite:
2> >(tee -a stderr.log >&2)
Wir verwenden wieder die Prozesssubstitution, um einen tee
zu erstellen Prozess, der von STDIN liest und es in stderr.log
ausgibt . tee
gibt seine Eingabe auf STDOUT zurück, aber da seine Eingabe unser STDERR ist, möchten wir tee
umleiten 's STDOUT wieder zu unserem STDERR. Dann verwenden wir die Dateiumleitung, um command
umzuleiten 's STDERR an den Eingang des FIFO (tee
's STDIN).
Siehe http://mywiki.wooledge.org/BashGuide/InputAndOutput
Die Prozessersetzung ist eines dieser wirklich schönen Dinge, die Sie als Bonus erhalten, wenn Sie bash
wählen als Ihre Shell im Gegensatz zu sh
(POSIX oder Bourne).
In sh
, müssten 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"
warum nicht einfach:
./aaa.sh 2>&1 | tee -a log
Dies leitet einfach stderr
um bis stdout
, also echos sowohl zum Log als auch zum Screen. Vielleicht übersehe ich etwas, weil einige der anderen Lösungen wirklich kompliziert erscheinen.
Hinweis: Seit der Bash-Version 4 können Sie |&
verwenden als Abkürzung für 2>&1 |
:
./aaa.sh |& tee -a log
Dies kann für Leute nützlich sein, die dies über Google finden. 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}