Supongo que aún desea ver STDERR y STDOUT en la terminal. Podrías elegir la respuesta de Josh Kelley, pero creo que mantener un tail
alrededor en segundo plano, lo que genera su archivo de registro muy pirateado y torpe. Observe cómo necesita mantener un exra FD y luego limpiarlo eliminándolo y técnicamente debería hacerlo en un trap '...' EXIT
.
Hay una mejor manera de hacer esto, y ya la has descubierto:tee
.
Solo que, en lugar de usarlo solo para su salida estándar, tenga una camiseta para la salida estándar y otra para la salida estándar. ¿Cómo lograrás esto? Sustitución de procesos y redirección de archivos:
command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
Dividámoslo y expliquemos:
> >(..)
>(...)
(sustitución de proceso) crea un FIFO y permite tee
Escúchalo. Luego, usa >
(redireccionamiento de archivos) para redirigir el STDOUT de command
al FIFO que tu primer tee
está escuchando.
Lo mismo para el segundo:
2> >(tee -a stderr.log >&2)
Usamos la sustitución de procesos nuevamente para hacer un tee
proceso que lee de STDIN y lo vuelca en stderr.log
. tee
genera su entrada en STDOUT, pero como su entrada es nuestro STDERR, queremos redirigir tee
's STDOUT a nuestro STDERR de nuevo. Luego usamos la redirección de archivos para redirigir command
's STDERR a la entrada de FIFO (tee
's STDIN).
Consulte http://mywiki.wooledge.org/BashGuide/InputAndOutput
La sustitución de procesos es una de esas cosas realmente encantadoras que obtienes como bonificación al elegir bash
como tu caparazón en lugar de sh
(POSIX o Bourne).
En sh
, tendrías que hacer las cosas 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"
por qué no simplemente:
./aaa.sh 2>&1 | tee -a log
Esto simplemente redirige stderr
a stdout
, por lo que tee hace eco tanto en el registro como en la pantalla. Tal vez me estoy perdiendo algo, porque algunas de las otras soluciones parecen realmente complicadas.
|&
como abreviatura de 2>&1 |
:
./aaa.sh |& tee -a log
Esto puede ser útil para las personas que lo encuentran a través de Google. Simplemente descomente el ejemplo que desea probar. Por supuesto, no dude en cambiar el nombre de los archivos de salida.
#!/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}