Presumo che tu voglia ancora vedere STDERR e STDOUT sul terminale. Potresti scegliere la risposta di Josh Kelley, ma trovo che mantenere un tail
intorno in background che emette il tuo file di registro molto hacker e goffo. Nota come devi mantenere un exra FD e successivamente eseguire la pulizia uccidendolo e tecnicamente dovresti farlo in un trap '...' EXIT
.
C'è un modo migliore per farlo, e lo hai già scoperto:tee
.
Solo, invece di usarlo solo per il tuo stdout, prendi una maglietta per stdout e una per stderr. Come realizzerai questo? Sostituzione del processo e reindirizzamento dei file:
command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
Dividiamolo e spieghiamo:
> >(..)
>(...)
(sostituzione del processo) crea un FIFO e lascia tee
ascoltalo. Poi usa >
(reindirizzamento file) per reindirizzare lo STDOUT di command
al FIFO che il tuo primo tee
è in ascolto.
Stessa cosa per il secondo:
2> >(tee -a stderr.log >&2)
Usiamo di nuovo la sostituzione del processo per creare un tee
processo che legge da STDIN e lo scarica in stderr.log
. tee
restituisce il suo input su STDOUT, ma poiché il suo input è il nostro STDERR, vogliamo reindirizzare tee
's STDOUT al nostro STDERR di nuovo. Quindi usiamo il reindirizzamento dei file per reindirizzare command
's STDERR all'input del FIFO (tee
's STDIN).
Vedi http://mywiki.wooledge.org/BashGuide/InputAndOutput
La sostituzione del processo è una di quelle cose davvero adorabili che ottieni come bonus scegliendo bash
come shell anziché sh
(POSIX o Bourne).
In sh
, dovresti fare le cose manualmente:
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"
perché non semplicemente:
./aaa.sh 2>&1 | tee -a log
Questo reindirizza semplicemente stderr
a stdout
, quindi tee fa eco sia a log che a screen. Forse mi sto perdendo qualcosa, perché alcune delle altre soluzioni sembrano davvero complicate.
Nota: Dalla versione 4 di bash puoi usare |&
come abbreviazione di 2>&1 |
:
./aaa.sh |& tee -a log
Questo può essere utile per le persone che lo trovano tramite Google. Decommenta semplicemente l'esempio che vuoi provare. Naturalmente, sentiti libero di rinominare i file di output.
#!/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}