Hay un par de formas más con las que puede abordar este problema. Suponiendo que uno de sus requisitos es ejecutar un script / función de shell que contenga algunos comandos de shell y verificar si el script se ejecutó correctamente y arrojar errores en caso de fallas.
Los comandos del shell generalmente se basan en los códigos de salida devueltos para informar al shell si tuvo éxito o falló debido a algunos eventos inesperados.
Entonces, lo que quiere hacer recae en estas dos categorías
- salir en caso de error
- salida y limpieza en caso de error
Dependiendo de cuál desee hacer, hay opciones de shell disponibles para usar. Para el primer caso, la carcasa ofrece una opción con set -e
y para la segunda se podría hacer un trap
sobreEXIT
¿Debo usar exit
en mi script / función?
El uso exit
generalmente mejora la legibilidad En ciertas rutinas, una vez que sepa la respuesta, querrá salir a la rutina de llamada inmediatamente. Si la rutina se define de tal manera que no requiere ninguna limpieza adicional una vez que detecta un error, no salir inmediatamente significa que debe escribir más código.
Por lo tanto, en los casos en que necesite realizar acciones de limpieza en el script para limpiar la terminación del script, se prefiere no usar exit
.
¿Debo usar set -e
para error al salir?
¡No!
set -e
fue un intento de agregar "detección automática de errores" al shell. Su objetivo era hacer que el shell abortara cada vez que ocurriera un error, pero conlleva muchos peligros potenciales, por ejemplo,
Los comandos que forman parte de una prueba if son inmunes. En el ejemplo, si espera que se rompa en la test
verificación en el directorio no existente, no lo haría, pasa a la condición else
set -e
f() { test -d nosuchdir && echo no dir; }
f
echo survived
Los comandos de una canalización que no sea la anterior son inmunes. En el siguiente ejemplo, porque el código de salida del comando ejecutado más recientemente (más a la derecha) se considera ( cat
) y fue exitoso. Esto podría evitarse estableciendo la set -o pipefail
opción, pero sigue siendo una advertencia.
set -e
somecommand that fails | cat -
echo survived
Recomendado para su uso: trap
a la salida
El veredicto es si desea poder manejar un error en lugar de salir a ciegas, en lugar de usar set -e
, use a trap
en la ERR
pseudo señal.
La ERR
trampa no es ejecutar código cuando el propio shell sale con un código de error distinto de cero, sino cuando cualquier comando ejecutado por ese shell que no es parte de una condición (como si cmd
, o cmd ||
) sale con un estado de salida distinto de cero. .
La práctica general es que definimos un controlador de trampas para proporcionar información de depuración adicional sobre qué línea y qué causa la salida. Recuerde que el código de salida del último comando que causó la ERR
señal aún estaría disponible en este punto.
cleanup() {
exitcode=$?
printf 'error condition hit\n' 1>&2
printf 'exit code returned: %s\n' "$exitcode"
printf 'the command executing at the time of the error was: %s\n' "$BASH_COMMAND"
printf 'command present on line: %d' "${BASH_LINENO[0]}"
# Some more clean up code can be added here before exiting
exit $exitcode
}
y usamos este controlador como se muestra a continuación en la parte superior del script que está fallando
trap cleanup ERR
Poniendo esto junto en un script simple que contenía false
en la línea 15, la información que obtendría como
error condition hit
exit code returned: 1
the command executing at the time of the error was: false
command present on line: 15
El trap
también proporciona opciones independientemente del error para ejecutar la limpieza al finalizar el shell (por ejemplo, el script de shell sale), en la señal EXIT
. También puede atrapar varias señales al mismo tiempo. La lista de señales admitidas para capturar se puede encontrar en trap.1p - página de manual de Linux
Otra cosa a tener en cuenta sería comprender que ninguno de los métodos proporcionados funciona si se trata de sub-shells involucrados, en cuyo caso, es posible que deba agregar su propio manejo de errores.
En un sub-shell con set -e
no funcionaría. El false
está restringido al sub-shell y nunca se propaga al shell padre. Para hacer el manejo de errores aquí, agregue su propia lógica para hacer(false) || false
set -e
(false)
echo survived
Lo mismo ocurre con trap
también. La lógica siguiente no funcionaría por las razones mencionadas anteriormente.
trap 'echo error' ERR
(false)