2011-05-10 11 views
9

Bash: Quiero ejecutar un comando y canalizar los resultados a través de algún filtro, pero si falla el comando, quiero volver valor de error del comando, no el valor de retorno aburrido del filtro:script bash: cómo guardar el valor de retorno del primer comando en una canalización?

Ej:

if !(cool_command | output_filter); then handle_the_error; fi 

o:

set -e 
cool_command | output_filter 

en cualquiera de los casos es el valor de retorno de cool_command que me importa - por el 'si' condición en el primer caso, o para salir de la secuencia de comandos en el segundo caso.

¿Hay alguna lengua limpia para hacer esto?

Respuesta

0

Si no necesita mostrar la salida de error del comando, se podría hacer algo como

if ! echo | mysql $dbcreds mysql; then 
    error "Could not connect to MySQL. Did you forget to add '--db-user=' or '--db-password='?" 
    die "Check your credentials or ensure server is running with /etc/init.d/mysqld status" 
fi 

En el ejemplo, el error y mueren son funciones definidas. en otro lugar en el guión. $ dbcreds también se define, aunque esto se crea a partir de opciones de línea de comandos. Si no hay ningún error generado por el comando, no se devuelve nada. Si ocurre un error, el texto será devuelto por este comando en particular.

corrígeme si me equivoco, pero me da la impresión de que realmente está buscando hacer algo un poco más complicado de lo

[ `id -u` -eq '0' ] || die "Must be run as root!" 

donde realmente se agarra el ID de usuario antes de la sentencia if, y luego realiza la prueba. Si lo hace de esta manera, podría mostrar el resultado si lo desea. Esto sería

UID=`id -u` 
if [ $UID -eq '0' ]; then 
    echo "User is root" 
else 
    echo "User is not root" 
    exit 1 ##set an exit code higher than 0 if you're exiting because of an error 
fi 
15

Utilice la variable integrada PIPESTATUS.

De man bash:

PIPESTATUS

una variable de matriz (ver Arrays a continuación) que contienen una lista de valores de estado de salida de los procesos en el primer plano más recientemente ejecutada canalización (que puede contener solo un único comando ).

+2

Solo para completar la respuesta, '[[$ {PIPESTATUS [0]} -ne 0]] && handle_the_error' – jozxyqk

0

La siguiente secuencia de comandos usa una fifo para filtrar la salida en un proceso separado. Esto tiene las siguientes ventajas sobre las otras respuestas. Primero, no es bash específico. En particular, no confía en PIPESTATUS. En segundo lugar, la salida no se detiene hasta que el comando se haya completado.

$ cat >test_filter.sh <<EOF 
#!/bin/sh 

cmd() 
{ 
    echo $1 
    echo $2 >&2 
    return $3 
} 

filter() 
{ 
    while read line 
    do  
      echo "... $line" 
    done 
} 

tmpdir=$(mktemp -d) 
fifo="$tmpdir"/out 
mkfifo "$fifo" 

filter <"$fifo" & 
pid=$! 
cmd a b 10 >"$fifo" 2>&1 
ret=$? 
wait $pid 
echo exit code: $ret 
rm -f "$fifo" 
rmdir "$tmpdir" 
EOF 
$ sh ./test_filter.sh 
... a 
... b 
exit code: 10 
Cuestiones relacionadas