Salida de comando de tubería a tee, sino también guardar el código de salida del comando [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Tengo un script de shell en el que envuelvo un comando (mvn clean install), para redirigir la salida a un archivo de registro.

#!/bin/bash
...
mvn clean install $@ | tee $logfile
echo $? # Does not show the return code of mvn clean install

Ahora bien, si mvn clean install falla con un error, quiero que mi script de shell wrapper también falle con ese error. Pero ya que estoy canalizando toda la salida a tee, no puedo acceder al código de retorno de mvn clean install, por lo que cuando acceso a $? después, siempre es 0 (desde los éxitos de tee).

Intenté dejar que el comando escribiera la salida de error en un archivo separado y comprobarlo después, pero la salida de error de mvn siempre está vacía (parece que solo escribe en stdout).

¿Cómo puedo conservar el código de retorno de mvn clean install pero aún canalizando la salida a un archivo de registro?

Author: ifischer, 2011-07-29

4 answers

Ya que estás ejecutando bash, puedes usar su variable PIP PIPESTATUS en lugar de $?:

mvn clean install $@ | tee $logfile
echo ${PIPESTATUS[0]}
 115
Author: Frédéric Hamidi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-29 10:42:19

Puede establecer el pipefail shell option opción activada para obtener el comportamiento que desea.

Del Manual de Referencia de Bash :

El estado de salida de una canalización es el estado de salida del último comando en la canalización, a menos que la opción pipefail esté habilitada (ver El Set Builtin). Si pipefail está habilitado, el estado de retorno de la canalización es el valor del último comando (situado más a la derecha) en salir con un estado distinto de cero, o cero si todos los comandos salen exitoso.

Ejemplo:

$ false | tee /dev/null ; echo $?
0
$ set -o pipefail
$ false | tee /dev/null ; echo $?
1

Para restaurar la configuración de la tubería original:

$ set +o pipefail
 157
Author: Jukka Matilainen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-27 16:57:05

Puede ejecutar el comando mvn y almacenar en caché el código de salida... Utilizo el comando" false " para mi ejemplo.

$ { false ; echo $? > /tmp/false.status ; } | tee $logfile
$ cat /tmp/false.status
1

De esta manera puede usar el contenido del archivo de estado para tomar decisiones adicionales.

Tengo curiosidad ahora si hay una manera más elocuente de lograr esto.

 10
Author: Demosthenex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-14 09:00:47

Solución alternativa (nota: una solución de perfer @Frederic):

f=`mktemp`
(mvn clean install $@; echo $?>$f) | tee $logfile
e=`cat $f` #error in variable e
rm $f
 3
Author: Karoly Horvath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-29 10:56:00