Para fines de prueba, me gustaría guardar stdout y stderr por separado para su inspección por código subsiguiente. Por ejemplo, una ejecución de prueba con una entrada errónea debería dar como resultado salida a stderr, pero nada en stdout, mientras que una ejecución de prueba con la entrada correcta debería dar como resultado salida a stdout, pero nada a stderr. El guardado debe ser sincrónico, para evitar condiciones de carrera con las pruebas (por lo que no puedo usar process substitution).Guardar stdout, stderr y stdout + stderr sincrónicamente
Para poder depurar la prueba después del hecho, I también necesito ver stdout y stderr en la secuencia de salida. Así que tengo que guardarlos en el mismo archivo/variable/lo que sea o enviarlos al terminal al mismo tiempo que los guardo por separado.
Para probar qué error ocurrió, I también necesita el código de salida del comando.
Por razones de eficiencia y precisión, por supuesto no puedo ejecutar cada prueba dos veces.
¿Es posible, por ejemplo, redirigir stdout a stdout.log, stderr a stderr.log, y ambos a output.log en el mismo comando? O para usar un comando síncronotee
por separado para stdout y stderr? ¿O para guardar una copia de stdout y stderr para separar las variables?
actualización: Parece que la solución de Tim casi obras (modificado para salida en el terminal en lugar de entrar a all.log):
$ set -o pipefail
$ {
{
echo foo | tee stdout.log 2>&3 3>&-
} 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1
foo
$ cat stdout.log
foo
$ cat stderr.log
$ {
{
echo foo >&2 | tee stdout.log 2>&3 3>&-
} 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1
foo
$ cat stdout.log
$ cat stderr.log
foo
$ bar=$({
{
echo foo | tee stdout.log 2>&3 3>&-
} 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1)
$ echo "$bar"
foo
$ cat stdout.log
foo
$ cat stderr.log
$ bar=$({
{
echo foo >&2 | tee stdout.log 2>&3 3>&-
} 2>&1 >&4 4>&- | tee stderr.log 2>&3 3>&-
} 3>&2 4>&1)
$ cat stdout.log
$ cat stderr.log
foo
$ echo "$bar"
foo
Esto parece funcionar a excepción de la última iteración, donde el valor de bar
se establece en los contenidos de stderr. ¿Alguna sugerencia para que todos estos funcionen?
Suponiendo que estamos hablando cadenas basadas en línea, podemos tubo de ambas corrientes a través, por ejemplo, 'sed' para agregar marcadores al comienzo de las líneas? Entonces, podríamos decir desde el archivo de registro qué línea vino de qué corriente. – Raphael
@Raphael: Debería poder preceder a 'tee' dentro de cada sustitución de proceso, por ejemplo:' exec>> (sed 's/^/de STDOUT: /' | tee-a mylog) 2>> (sed 's/^/desde STDERR:/'| tee -a mylog> & 2) '(no probado). Esto provocaría que la salida del terminal también tenga esos prefijos, por cierto. –
¡Genial! ¿Eso no invalida parte de la cita que das? Ahora tenemos un archivo de salida compartido sincronizado y aún sabemos cuál fue cuál o me falta algo. – Raphael