Salir de una tubería si falla un comando anterior

Salir de una tubería si falla un comando anterior

Estoy intentando verificar la cantidad de trabajos de PBS en ejecución y en cola analizando el resultado de qstat -tn1un bashscript. Hasta ahora, esto ha funcionado:

count ()
{
    qstat -tn1 | awk '
        BEGIN { R = 0; Q = 0; }
        $10 == "R" { R++ }
        $10 == "Q" { Q++ }
        END { print R, Q }'
}

if read -r R Q < <(count)
    ...

Sin embargo, veo que qstaten ocasiones falla por motivos desconocidos. En ese caso, no imprime nada stdouty algún mensaje de error stderry sale con un estado distinto de cero (bastante estándar). Sin embargo, awkno sabe que qstatfalló y felizmente imprime 0 0la entrada vacía que recibió. Luego readasigna 0 a ambos Ry Qsin saber que qstaten realidad falló.

  1. Necesito inicializar Ry Qcon 0 en el BEGINbloque del awkscript, porque puede que no haya procesos en ejecución o procesos en cola, y necesito imprimir 0, no solo una cadena vacía, para la cantidad de dichos procesos.
  2. Podría hacerlo set -o pipefail, lo que permitiría countsalir con un estado distinto de cero, pero readno puedo ver el estado de salida y, de todos modos awk, se ejecuta e imprime 0 0para la entrada vacía.
  3. Podría probar una canalización con nombre y subprocesos, pero tener que administrarlos parece una exageración y demasiado complicado.

¿Existe alguna buena manera de permitir que la persona que llama countdetecte su falla?

Respuesta1

Creo que leer counten una sustitución de proceso le impide obtener su estado de devolución. Entonces no lo hagas. En su lugar, almacene el resultado en una variable o utilice una tubería.

count=$(count)
if [ $? -eq 0 ]; then
  read -r R Q <<<"$count"

o

set -o pipefail
if count | { read -r R Q; … }

Otra posibilidad es utilizar la PIPESTATUSvariable para comprobar el estado de devolución del primer comando.

count=$(qstat -tn1 | awk …)
if ((${PIPESTATUS[0]} == 0)); then
  read P Q

Alternativamente, haga arreglos para que awk imprima algo distintivo (por ejemplo, nada) cuando su entrada esté vacía.

awk '
    BEGIN { R = 0; Q = 0; }
    $10 == "R" { R++ }
    $10 == "Q" { Q++ }
    END { if (NR) print R, Q }'

Puede probar si la entrada de un comando está vacía con ifnefrommásutilsootros metodos. Pero como estás ingresando a awk, también puedes hacerlo directamente dentro del script awk que ya tienes.

Si necesita obtener el estado de retorno del qstatcomando, puede enviarlo a awk como una línea de entrada adicional. Para facilitar el análisis, haga que la última línea tenga un formato único.

{
  qstat -tn1
  echo exit_code = $?
} | awk '
    /^exit_code = / { status = $3 }
    END { if (status == 0) print Q, R }
'

Respuesta2

Este:

count ()
{
    { qstat -tn1 || echo "EPIC FAIL" } | awk '
        BEGIN { R = 0; Q = 0; }
        $10 == "R" { R++ }
        $10 == "Q" { Q++ }
        END { print R, Q }'
}

if read -r R Q < <(count)
    ...

Si qstattiene éxito, su salida se envía a awk. Si qstatdevuelve un estado distinto de cero, se envía el texto "EPIC FAIL" awk.

Este es sólo un ejemplo. Reemplace el eco con algo apropiado que pueda manejar dentro awko con if read.

información relacionada