¿Cómo escribo un error estándar en un archivo mientras uso "tee" con una tubería?

Resuelto jparanich asked hace 15 años • 12 respuestas

Sé cómo usarlo teepara escribir la salida ( salida estándar ) de aaa.shto bbb.out, mientras sigo mostrándola en la terminal:

./aaa.sh | tee bbb.out

¿Cómo podría escribir ahora también un error estándar en un archivo llamado ccc.out, sin dejar de mostrarlo?

jparanich avatar Mar 28 '09 08:03 jparanich
Aceptado

Supongo que aún desea ver el error estándar y la salida estándar en el terminal. Podrías optar por la respuesta de Josh Kelley , pero encuentro que mantener un tailentorno en segundo plano genera tu archivo de registro muy complicado y complicado. Observe cómo necesita mantener un descriptor de archivo adicional y luego realizar una limpieza eliminándolo y técnicamente debería hacerlo en un archivo trap '...' EXIT.

Hay una manera mejor de hacer esto y ya la has descubierto: tee.

Solo que, en lugar de usarlo simplemente para la salida estándar, tenga una T para la salida estándar y otra para el error 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 procesos) crea un FIFO y teelo escuchamos. Luego, utiliza >(redirección de archivos) para redirigir la salida estándar commandal FIFO en el que teeestá escuchando el primero.

Lo mismo para el segundo:

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

Usamos la sustitución de procesos nuevamente para crear un teeproceso que lea la entrada estándar y la descargue en stderr.log. teedevuelve su entrada a la salida estándar, pero dado que su entrada es nuestro error estándar, queremos redirigir teela salida estándar a nuestro error estándar nuevamente. Luego usamos la redirección de archivos para redirigir commandel error estándar a la entrada FIFO ( teeentrada estándar de).

Ver entrada y salida

La sustitución de procesos es una de esas cosas realmente hermosas que obtienes como beneficio adicional al elegir Bash como tu shell 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"
lhunath avatar Mar 28 '2009 07:03 lhunath

Simplemente:

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

Esto simplemente redirige el error estándar a la salida estándar, por lo que tee hace eco tanto en el registro como en la pantalla. Quizás me estoy perdiendo algo, porque algunas de las otras soluciones parecen realmente complicadas.

Nota: Desde la versión 4 de Bash, puede utilizar |&como abreviatura 2>&1 |:

./aaa.sh |& tee -a log
user542833 avatar Aug 09 '2011 05:08 user542833

Esto puede resultar útil para las personas que encuentran esto a través de Google. Simplemente descomente el ejemplo que desea probar. Por supuesto, siéntase libre de 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}
Anthony avatar Oct 09 '2013 18:10 Anthony