Saltar al contenido

Generar error en un script Bash

Haz todo lo posible por interpretar el código bien previamente a usarlo a tu proyecto si ttienes algo que aportar puedes dejarlo en los comentarios.

Solución:

Esto depende de dónde desee que se almacene el mensaje de error.

Puede hacer lo siguiente:

echo "Error!" > logfile.log
exit 125

O lo siguiente:

echo "Error!" 1>&2
exit 64

Cuando genera una excepción, detiene la ejecución del programa.

También puedes usar algo como exit xxx dónde xxx es el código de error que puede querer volver al sistema operativo (de 0 a 255). Aquí 125 y 64 son solo códigos aleatorios con los que puede salir. Cuando necesite indicar al sistema operativo que el programa se detuvo de manera anormal (por ejemplo, se produjo un error), debe pasar un código de salida distinto de cero para exit.

Como señaló @chepner, puede hacer exit 1, lo que significará un error no especificado.

Manejo básico de errores

Si su corredor de casos de prueba devuelve un código distinto de cero para las pruebas fallidas, simplemente puede escribir:

test_handler test_case_x; test_result=$?
if ((test_result != 0)); then
  printf '%sn' "Test case x failed" >&2  # write error message to stderr
  exit 1                                  # or exit $test_result
fi

O incluso más corto:

if ! test_handler test_case_x; then
  printf '%sn' "Test case x failed" >&2
  exit 1
fi

O el más corto:

test_handler test_case_x ||  printf '%sn' "Test case x failed" >&2; exit 1; 

Para salir con el código de salida de test_handler:

test_handler test_case_x ||  ec=$?; printf '%sn' "Test case x failed" >&2; exit $ec; 

Manejo avanzado de errores

Si desea adoptar un enfoque más completo, puede tener un controlador de errores:

exit_if_error() 
  local exit_code=$1
  shift
  [[ $exit_code ]] &&               # do nothing if no error code passed
    ((exit_code != 0)) &&          # do nothing if error code is 0
      printf 'ERROR: %sn' "[email protected]" >&2 # we can use better logging here
      exit "$exit_code"             # we could also check to make sure
                                    # error code is numeric when passed
    

luego invocalo después de ejecutar tu caso de prueba:

run_test_case test_case_x
exit_if_error $? "Test case x failed"

o

run_test_case test_case_x || exit_if_error $? "Test case x failed"

Las ventajas de tener un controlador de errores como exit_if_error están:

  • podemos estandarizar toda la lógica de manejo de errores, como el registro, la impresión de un seguimiento de la pila, la notificación, la limpieza, etc., en un solo lugar
  • Al hacer que el controlador de errores obtenga el código de error como argumento, podemos evitar que la persona que llama el desorden de if bloques que prueban códigos de salida en busca de errores
  • si tenemos un manejador de señales (usando trampa), podemos invocar el manejador de errores desde allí

Biblioteca de registro y manejo de errores

Aquí hay una implementación completa del manejo y registro de errores:

https://github.com/codeforester/base/blob/master/lib/stdlib.sh


Artículos Relacionados

  • Manejo de errores en Bash
  • El comando incorporado ‘llamador’ en Bash Hackers Wiki
  • ¿Existe algún código de estado de salida estándar en Linux?
  • BashFAQ / 105 – ¿Por qué el set -e (o set -o errexit, o trap ERR) no hace lo que esperaba?
  • Equivalente de __FILE__, __LINE__ en Bash
  • ¿Hay un comando TRY CATCH en Bash?
  • Para agregar un seguimiento de pila al controlador de errores, es posible que desee ver esta publicación: Seguimiento de programas ejecutados llamados por un script Bash
  • Ignorar errores específicos en un script de shell
  • Captura de códigos de error en una tubería de shell
  • ¿Cómo administro la verbosidad del registro dentro de un script de shell?
  • ¿Cómo registrar el nombre de la función y el número de línea en Bash?
  • Son corchetes dobles [[ ]]preferible a los corchetes simples [ ] en Bash?

Hay un par de formas más de 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, el caparazón proporciona una opción con set -e y por el segundo podrías hacer un trap sobre EXIT

Debo usar exit en mi script / función?

Utilizando 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 está definida de tal manera que no requiere más limpieza 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 por 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 se producía 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 el test Verifique 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, debido a que el código de salida del comando ejecutado más recientemente (más a la derecha) se considera ( cat) y tuvo éxito. Esto podría evitarse estableciendo el 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, utilizar una trap sobre el ERR pseudo señal.

los ERR trap 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 en if cmd, o cmd ||) sale con un estado de salida distinto de cero.

La práctica general es definir un controlador de trampas para proporcionar información de depuración adicional sobre qué línea y qué causa la salida. Recuerde el código de salida del último comando que provocó la ERR la señal todavía estaría disponible en este punto.

cleanup() 
    exitcode=$?
    printf 'error condition hitn' 1>&2
    printf 'exit code returned: %sn' "$exitcode"
    printf 'the command executing at the time of the error was: %sn' "$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 solo 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

los 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 atrapar 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-caparazón con set -e no funcionaría. los 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 pasa con trap además. La lógica siguiente no funcionaría por las razones mencionadas anteriormente.

    trap 'echo error' ERR
    (false)
    

Si para ti ha sido de ayuda nuestro artículo, agradeceríamos que lo compartas con otros desarrolladores y nos ayudes a dar difusión a nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *