¿Cómo evitar que un comando active la trampa ERR?

¿Cómo evitar que un comando active la trampa ERR?

Estoy usando una trampa ERR para detectar cualquier error en mi script bash y mostrar lo que sucedió en el registro. (similar a esta pregunta:Trampa, ERR y eco de la línea de error) Funciona como se esperaba. El único problema es que en algún momento de mi script se espera que aparezca un código de salida! = 0. ¿Cómo puedo hacer que la trampa no se active en esta situación?

Aquí hay un código:

err_report() {
    echo "errexit on line $(caller)" | tee -a $LOGFILE 1>&2
}

trap err_report ERR

Luego, más adelante en el guión:

<some command which occasionally will return a non-zero exit code>

if [ $? -eq 0 ]; then
    <handle stuff>
fi

Cada vez que el comando devuelve un valor distinto de cero, se activa mi trampa. ¿Puedo evitar esto sólo para esta parte del código?

Revisé esta pregunta:Comportamiento correcto de las trampas EXIT y ERR al usar `set -eu` pero realmente no entiendo cómo aplicarlo a mi caso, si es que es aplicable.

Respuesta1

Un ERR trapno se activará si se "capta" inmediatamente un código de error, lo que significa que ustedpoderuse ifdeclaraciones y todo eso sin tener que activar y desactivar la captura de errores todo el tiempo. Sin embargo, tuno puedouse la verificación $?para el control de flujo, porque cuando llegue a esa verificación, ya (puede) tener el error no detectado.

Si tienes un comando esperas que falle, ynoSi desea que esas fallas activen el trap, simplemente tiene que detectar la falla. Envolverlos en una ifdeclaración es complicado y detallado, pero esta taquigrafía funciona muy bien:

/bin/false || :  # will not trigger an ERR trap

Sin embargo, si desea hacer cosas cuando falla un comando, ifestará bien aquí:

if ! /bin/false; then
    echo "this was not caught by the trap!"
fi

O alternativamente, elsetambién detectará el estado de error:

if /bin/false; then
    : # dead code
else
    echo "this was not caught by the trap!"
fi

En resumen, set -ey trap "command" ERRsolo se activa si hay una condición de error que no se tiene en cuenta inmediata e intrínsecamente.

Respuesta2

Puede habilitar/deshabilitar la ERRcaptura durante partes de su código según sea necesario.

#!/bin/bash
err_report() {
    echo "errexit on line $(caller)"
}
trap err_report ERR
trap - ERR             # disable ERR trap
false
if [ $? -eq 0 ]; then
    printf "OK\n"
else
    printf "FAIL\n"    # prints FAIL
fi
trap err_report ERR    # enable ERR trap
false                  # prints errexit on line 14

Respuesta3

A menudo encuentro que quiero evitar la trampa ERR pero tampoco quiero descartar el código de retorno de mi función. Entonces el patrón que uso es este:

RC=0
some_function || RC=$?

Luego hago lo que sea necesario con RC.

Respuesta4

La ERRtrampa obedece las mismas reglas que set -e, es decir, no tiene efecto sobre los comandos que se utilizan como condiciones. Entonces,

trap "echo error" ERR
false                     # this should trigger the trap
if ! false; then          # this shouldn't
     echo handle stuff
fi

Recuerde que el comando en elif condición puede sercualquiercomando, no tiene por qué serlo [ .. ]. Por lo tanto, si solo desea una evaluación verdadero/falso del estado de salida de un comando, utilícela directamente en la ifcondición.

Si necesita guardar el código de salidayEvita la ERRtrampa, tendrás que hacer algo como

somecmd && :; ret=$?

Aquí, &&aplastará la ERRtrampa, pero como solo se ejecuta si el código de salida es cero, sabremos que el código de salida es el mismo después :.

Quizás quieras comprobarBashFAQ 105: ¿Por qué set -e (o set -o errexit, o trap ERR) no hace lo que esperaba?

información relacionada