2012-01-12 28 views
11

¿Cómo obtengo el código de retorno correcto de una aplicación de línea de comandos de Unix después de haberlo procesado a través de otro comando que tuvo éxito?Salida del comando Pipe, pero conserve el código de error

En detalle, aquí está la situación:

$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file} -- when only the tar command fails $?=0 
$ echo $? 
0 

Y, lo que me gustaría ver es:

$ tar -cEvhf - -I ${sh_tar_inputlist} 2>${sh_tar_error_file} | gzip -5 -c > ${sh_tar_file} 
$ echo $? 
1 

¿Alguien sabe cómo lograr esto?

+0

'$?' Contiene el código de error. Podrías guardarlo en una variable. –

+1

necesito guardar el código de retorno del comando intermedio, no el último comando. – SamiBOB

Respuesta

3

Aquí hay una solución general que usa solo shell POSIX y no hay archivos temporales:

A partir de la canalización: foo | bar | Baz

exec 4>&1 
error_statuses=`((foo || echo "0:$?" >&3) | 
     (bar || echo "1:$?" >&3) | 
     (baz || echo "2:$?" >&3)) 3>&1 >&4` 
exec 4>&- 

$ error_statuses contiene los códigos de estado de cualquier proceso fracasaron, en orden aleatorio, con índices de decir que comando emite cada estado.

# if "bar" failed, output its status: 
echo $error_statuses | grep '1:' | cut -d: -f2 

# test if all commands succeeded: 
test -z "$error_statuses" 

# test if the last command succeeded: 
echo $error_statuses | grep '2:' >/dev/null 
4

Mire $PIPESTATUS que es una variable de matriz que contiene estados de salida. Por lo tanto, ${PIPESTATUS[0]} contiene el estado de salida del primer comando en el conducto, ${PIPESTATUS[1]} el estado de salida del segundo comando, y así sucesivamente.

Por ejemplo:

$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file} 
$ echo ${PIPESTATUS[0]} 

Para imprimir use todos los estados:

$ echo ${PIPESTATUS[@]} 
+1

Thx, pero no uso bash con mis scripts. Trabajo con #!/Bin/sh – SamiBOB

+0

@dogbane, cualquier diferencia entre '$ {PIPESTATUS [*]}' y '$ {PIPESTATUS [@]}'? Siempre utilizo el anterior ... – fge

+2

Votación descendente, $ PIPESTATUS ** NO EXISTE ** en POSIX. –

1

Como han señalado otros, algunas conchas modernas proporcionan PIPESTATUS para obtener esta información. En sh clásico, que es un poco más difícil, y hay que utilizar un FIFO:

 
#!/bin/sh 

trap 'rm -rf $TMPDIR' 0 
TMPDIR=$(mktemp -d) 
mkfifo ${FIFO=$TMPDIR/fifo} 

cmd1 > $FIFO & 
cmd2 < $FIFO 
wait $! 
echo The return value of cmd1 is $? 

(Bueno, no es necesario utilizar un FIFO Puede hacer que los comandos temprano en la tubería eco de un estado. variable y evalúa eso en el shell principal, redirige los descriptores de archivos por todos lados y básicamente dobla hacia atrás para verificar cosas, pero usar un fifo es mucho, mucho más fácil.)

+0

Hola, probé esta técnica pero no funciona: probé:/usr/bin/tar -cMEvhf - -I/tmp/test.tmp> $ FIFO & gzip -5 -c < $FIFO > /tmp/test.bkz espera $! echo ¿El valor de retorno de cmd1 es $? – SamiBOB

+0

¿Qué error obtuviste? –

+0

incluso cuando cmd1 falla, el $? = 0 – SamiBOB

Cuestiones relacionadas