Je suppose que vous voulez toujours voir STDERR et STDOUT sur le terminal. Vous pourriez opter pour la réponse de Josh Kelley, mais je trouve que garder un tail
autour en arrière-plan qui génère votre fichier journal très hackish et maladroit. Remarquez comment vous devez conserver un exra FD et faire le nettoyage par la suite en le tuant et, techniquement, vous devriez le faire dans un trap '...' EXIT
.
Il existe une meilleure façon de procéder, et vous l'avez déjà découverte :tee
.
Seulement, au lieu de simplement l'utiliser pour votre stdout, ayez un tee pour stdout et un pour stderr. Comment allez-vous accomplir cela ? Substitution de processus et redirection de fichiers :
command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
Séparons-le et expliquons :
> >(..)
>(...)
(substitution de processus) crée un FIFO et laisse tee
écoutez dessus. Ensuite, il utilise >
(redirection de fichier) pour rediriger le STDOUT de command
au FIFO que votre premier tee
écoute.
Même chose pour le second :
2> >(tee -a stderr.log >&2)
Nous utilisons à nouveau la substitution de processus pour créer un tee
processus qui lit à partir de STDIN et le vide dans stderr.log
. tee
renvoie son entrée sur STDOUT, mais puisque son entrée est notre STDERR, nous voulons rediriger tee
's STDOUT à notre STDERR à nouveau. Ensuite, nous utilisons la redirection de fichiers pour rediriger command
's STDERR à l'entrée de la FIFO (tee
's STDIN).
Voir http://mywiki.wooledge.org/BashGuide/InputAndOutput
La substitution de processus est l'une de ces choses vraiment adorables que vous obtenez en bonus en choisissant bash
comme votre shell par opposition à sh
(POSIX ou Bourne).
En sh
, il faudrait faire les choses manuellement :
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"
pourquoi pas simplement :
./aaa.sh 2>&1 | tee -a log
Cela redirige simplement stderr
à stdout
, donc tee fait écho à la fois au journal et à l'écran. Peut-être qu'il me manque quelque chose, car certaines des autres solutions semblent vraiment compliquées.
Remarque : Depuis la version 4 de bash, vous pouvez utiliser |&
comme abréviation de 2>&1 |
:
./aaa.sh |& tee -a log
Cela peut être utile pour les personnes qui trouvent cela via google. Décommentez simplement l'exemple que vous voulez essayer. Bien sûr, n'hésitez pas à renommer les fichiers de sortie.
#!/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}