Verificación del código de retorno de subcomandos en tuberías de Linux

En el entorno de Bash, la variable $? se emplea comúnmente para recuperar el código de retorno del último comando ejecutado. Sin embargo, al trabajar con tuberías (pipes), esta variable solo refleja el estado del comando final en la cadena.

Por ejemplo, considere una tubería donde un comando principal genera una salida que se redirige a un procesador de registros:

comando_primario 2> "directorio"/registro_primario.log | herramienta_procesamiento.py -n 3 "directorio"/registro_primario.log 500M

Consultar $? después de esta tubería proporcionará el código de retorno de herramienta_procesamiento.py, no el de comando_primario.

Para acceder a los códigos de retorno individuales de cada comando en una tubería, Bash ofrece la variable de arreglo PIPESTATUS. Cada elemento del arreglo, indexado desde cero, almacena el código de retorno del comando correspondiente en la tubería.

Consideraciones importantes al utilizar PIPESTATUS:

  • El arreglo PIPESTATUS se actualiza con la ejecución de cada nuevo comando. Por lo tanto, su contenido representa los códigos de retorno de la última tubería o comando ejecutado.
  • Si el comando anterior no es una tubería sino un comando aislado, el código de retorno se almacena en ${PIPESTATUS[0]}, el cual coincide con el valor de $?.
  • Cualquier operación que involucre PIPESTATUS puede modificar su estado, ya que ejecutar un comando nuevo lo sobrescribe.

Para ilustrar su uso, observe el siguiente ejemplo:

comando_a | comando_b
if [ "${PIPESTATUS[0]}" -ne 0 ]; then echo "El primer comando falló: ${PIPESTATUS[@]}"; fi

En esta secuencia, ${PIPESTATUS[0]} contendría el código de retorno de comando_a, y ${PIPESTATUS[1]} el de comando_b. No obstante, tras ejecutar la sentencia if, el arreglo se actualiza con el código de retorno del comando de prueba ([ ... ]), lo que puede distorsionar los valores originales.

Para preservar los códigos de retorno y analizarlos posteriormente, se recomienda copiar el arreglo a una variable local inmediatamente después de la tubería:

primera_etapa | segunda_etapa | tercera_etapa
codigos_ret=( "${PIPESTATUS[@]}" )
echo "Código de primera_etapa: ${codigos_ret[0]}"
echo "Código de segunda_etapa: ${codigos_ret[1]}"
echo "Código de tercera_etapa: ${codigos_ret[2]}"

Este enfoque garantiza que los valores se mantengan intactos para su verificación, independientemente de comandos subsecuentes.

Aplicando esta técnica al ejemplo inicial, se podría estructurar la tubería y verificar el código del comando primario así:

comando_primario 2> "directorio"/registro_primario.log | herramienta_procesamiento.py -n 3 "directorio"/registro_primario.log 500M
estado_tuberia=( "${PIPESTATUS[@]}" )
exit "${estado_tuberia[0]}"

De esta manera, el script finaliza con el código de retorno deseado del primer comando en la tubería.

Etiquetas: bash linux shell scripting pipestatus exit status

Publicado el 6-26 22:42