Generar error en un script Bash

111
Naveen Kumar 2015-05-07 03:30.

Quiero generar un error en un script Bash con el mensaje "¡¡¡Casos de prueba fallaron !!!". ¿Cómo hacer esto en Bash?

Por ejemplo:

if [ condition ]; then
    raise error "Test cases failed !!!"
fi

6 answers

128
ForceBru 2015-05-07 03:33.

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 puede usar algo como exit xxxdónde xxxestá el código de error que quizás desee volver al sistema operativo (de 0 a 255). Aquí 125y 64solo hay códigos aleatorios con los que puede salir. Cuando necesite indicar al sistema operativo que el programa se detuvo de forma anormal (por ejemplo, se produjo un error), debe pasar un código de salida distinto de cero a exit.

Como Generar error en un script Bash @chepner , puede hacerlo exit 1, lo que significará un error no especificado .

40
codeforester 2018-05-10 18:30.

Manejo básico de errores

Si su corredor de casos de prueba devuelve un ¿Existen códigos de estado de salida estándar en Linux? para las pruebas fallidas, simplemente puede escribir:

test_handler test_case_x; test_result=$?
if ((test_result != 0)); then
  printf '%s\n' "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 '%s\n' "Test case x failed" >&2
  exit 1
fi

O el más corto:

test_handler test_case_x || { printf '%s\n' "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 '%s\n' "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: %s\n' "[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_errorson:

  • 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 manejador de errores obtenga el código de error como argumento, podemos evitar que la persona que llama del desorden de ifbloques que prueban los 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

10
Inian 2018-05-11 00:36.

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, la carcasa ofrece una opción con set -ey para la segunda se podría hacer un trapsobreEXIT

¿Debo usar exiten mi script / función?

El uso exitgeneralmente 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 -epara error al salir?

¡No!

set -efue 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 la testverificació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 en una tubería 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 pipefailopción, pero sigue siendo una advertencia.

    set -e
    somecommand that fails | cat -
    echo survived 
    

Recomendado para su uso: trapa 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 trapen la ERRpseudo señal.

La ERRtrampa 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 ERRseñ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 falseen 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 traptambién proporciona opciones independientemente del error para ejecutar la limpieza al finalizar el shell (por ejemplo, su script de shell sale), en 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 -eno funcionaría. El falsese limita a la sub-shell y nunca se propagan a la carcasa principal. 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 traptambién. La lógica siguiente no funcionaría por las razones mencionadas anteriormente.

    trap 'echo error' ERR
    (false)
    
5
Paul Hodges 2018-05-12 06:49.

Aquí hay una trampa simple que imprime el último argumento de lo que falló en STDERR, informa la línea en la que falló y sale del script con el número de línea como código de salida. Tenga en cuenta que estas no siempre son buenas ideas, pero esto demuestra alguna aplicación creativa sobre la que podría desarrollar.

trap 'echo >&2 "$_ at $LINENO"; exit $LINENO;' ERR

Lo puse en un script con un bucle para probarlo. Solo busco un acierto en algunos números aleatorios; puede utilizar pruebas reales. Si necesito fianza, llamo falso (lo que desencadena la trampa) con el mensaje que quiero lanzar.

Para una funcionalidad elaborada, haga que la trampa llame a una función de procesamiento. Siempre puede usar una declaración de caso en su arg ($ _) si necesita hacer más limpieza, etc. Asigne a una var para un poco de azúcar sintáctico -

trap 'echo >&2 "$_ at $LINENO"; exit $LINENO;' ERR
throw=false
raise=false

while :
do x=$(( $RANDOM % 10 ))
   case "$x" in
   0) $throw "DIVISION BY ZERO" ;;
   3) $raise "MAGIC NUMBER"     ;;
   *) echo got $x               ;;
   esac
done

Salida de muestra:

# bash tst
got 2
got 8
DIVISION BY ZERO at 6
# echo $?
6

Obviamente, podrías

runTest1 "Test1 fails" # message not used if it succeeds

Mucho espacio para mejorar el diseño.

Los inconvenientes incluyen el hecho de que falseno es bonito (por lo tanto, el azúcar), y otras cosas que disparan la trampa pueden parecer un poco estúpidas. Aún así, me gusta este método.

4
alamoot 2018-05-17 03:18.

Tiene 2 opciones: Redirigir la salida del script a un archivo, Introducir un archivo de registro en el script y

  1. Redirigir la salida a un archivo :

Aquí asume que el script genera toda la información necesaria, incluidos los mensajes de advertencia y error. A continuación, puede redirigir la salida a un archivo de su elección.

./runTests &> output.log

El comando anterior redirige tanto la salida estándar como la salida de error a su archivo de registro.

Con este enfoque, no es necesario introducir un archivo de registro en el script, por lo que la lógica es un poco más sencilla.

  1. Introduzca un archivo de registro en el script :

En su secuencia de comandos, agregue un archivo de registro codificándolo:

logFile='./path/to/log/file.log'

o pasándolo por un parámetro:

logFile="${1}"  # This assumes the first parameter to the script is the log file

Es una buena idea agregar la marca de tiempo en el momento de la ejecución al archivo de registro en la parte superior del script:

date '+%Y%-m%d-%H%M%S' >> "${logFile}"

Luego puede redirigir sus mensajes de error al archivo de registro

if [ condition ]; then
    echo "Test cases failed!!" >> "${logFile}"; 
fi

Esto agregará el error al archivo de registro y continuará la ejecución. Si desea detener la ejecución cuando ocurren errores críticos, puede exitel script:

if [ condition ]; then
    echo "Test cases failed!!" >> "${logFile}"; 
    # Clean up if needed
    exit 1;
fi

Tenga en cuenta que exit 1indica que el programa detiene la ejecución debido a un error no especificado. Puede personalizar esto si lo desea.

Con este enfoque, puede personalizar sus registros y tener un archivo de registro diferente para cada componente de su secuencia de comandos.


Si tiene un script relativamente pequeño o desea ejecutar el script de otra persona sin modificarlo, el primer enfoque es más adecuado.

Si siempre desea que el archivo de registro esté en la misma ubicación, esta es la mejor opción de la 2. Además, si ha creado una secuencia de comandos grande con varios componentes, es posible que desee registrar cada parte de manera diferente y el segundo enfoque es su único opción.

3
Adam Katz 2018-05-11 08:47.

A menudo encuentro útil escribir una función para manejar mensajes de error para que el código sea más limpio en general.

# Usage: die [exit_code] [error message]
die() {
  local code=$? now=$(date +%T.%N)
  if [ "$1" -ge 0 ] 2>/dev/null; then  # assume $1 is an error code if numeric
    code="$1"
    shift
  fi
  echo "$0: ERROR at ${now%???}${1:+: $*}" >&2
  exit $code
}

Esto toma el código de error del comando anterior y lo usa como el código de error predeterminado al salir de todo el script. También toma nota del tiempo, con microsegundos donde se admite (la fecha de GNU %Nes nanosegundos, que truncamos a microsegundos más tarde).

Si la primera opción es cero o un entero positivo, se convierte en el código de salida y lo eliminamos de la lista de opciones. Luego informamos el mensaje al error estándar, con el nombre del script, la palabra "ERROR" y el tiempo (usamos la expansión de parámetros para truncar nanosegundos a microsegundos, o para tiempos no GNU, truncar, por ejemplo, 12:34:56.%Na 12:34:56). Se agregan dos puntos y un espacio después de la palabra ERROR, pero solo cuando se proporciona un mensaje de error. Finalmente, salimos del script usando el código de salida previamente determinado, activando las trampas de forma normal.

Algunos ejemplos (supongamos que el código reside en script.sh):

if [ condition ]; then die 123 "condition not met"; fi
# exit code 123, message "script.sh: ERROR at 14:58:01.234564: condition not met"

$command |grep -q condition || die 1 "'$command' lacked 'condition'"
# exit code 1, "script.sh: ERROR at 14:58:55.825626: 'foo' lacked 'condition'"

$command || die
# exit code comes from command's, message "script.sh: ERROR at 14:59:15.575089"

Related questions

MORE COOL STUFF

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que tiene 'envenenamiento por mercurio y plomo' probablemente por voltear 'casas asquerosas'

La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

La estrella de 'Love Is Blind' Brennon Lemieux responde a los cargos de violencia doméstica

Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia Judd en un momento festivo de pánico

Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Experto en lenguaje corporal explica los 'paralelos' entre Kate Middleton y la princesa Diana

Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los láseres arrojan luz sobre por qué necesita cerrar la tapa antes de descargar

Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

¿Caduca el repelente de insectos?

¿Caduca el repelente de insectos?

¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?

Estados Unidos podría evitarse el horror del nuevo gran horneado británico

Estados Unidos podría evitarse el horror del nuevo gran horneado británico

Si este tráiler de pesadilla de la temporada más reciente de Great British Bake Off te asustó y te hizo no volver a ver el programa, es posible que tengas suerte: PBS no ha decidido si se transmitirá o no la última temporada en los Estados Unidos. actualización, para aquellos que no siguen sin aliento este tipo de drama de nicho: el presentador Paul Hollywood y la hermosa carpa llena de batidoras de colores pastel y cuadros se trasladaron de la BBC al Canal 4; Mary Berry, Sue Perkins y Mel Giedroyc renunciaron.

Atún como Oh, Hello llega a Netflix

Atún como Oh, Hello llega a Netflix

Foto: Netflix Oh, Hello On Broadway (Netflix): Después de llegar a Broadway el año pasado, los dos locos del Upper West Side interpretados por John Mulaney y Nick Kroll finalmente llegaron a Netflix. El especial consta del espectáculo en el escenario, algunos momentos entre bastidores y un invitado muy especial de “Too Much Tuna”.

Actualice a un Sonicare por tan solo $ 30

Actualice a un Sonicare por tan solo $ 30

¿Quiere probar un cepillo de dientes Sonicare sin gastar mucho dinero en uno de sus modelos favoritos de gama alta? Puede comprar un kit de la Serie 2 o Serie 3 por tan solo $ 30 hoy en Amazon. Haga clic aquí para ver la lista completa de modelos elegibles y tenga en cuenta que se descontarán $ 10 adicionales en su carrito.

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Ponle una tapa. En realidad, ponle una tapa a todo. Consigue 12 tapas de cocina elásticas de silicona por $14. [Exclusivo]

Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

Patinaje artístico de EE. UU. 'frustrado' por falta de decisión final en evento por equipos, pide una decisión justa

El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Los compradores de Amazon dicen que duermen 'como un bebé mimado' gracias a estas fundas de almohada de seda que cuestan tan solo $ 10

Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

Se busca al corredor de los Bengals Joe Mixon por orden de arresto emitida por presuntamente apuntar con un arma de fuego a una mujer

El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

Profesor de la Universidad de Purdue arrestado por presuntamente traficar metanfetamina y proponer favores sexuales a mujeres

El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Concept Drift: el mundo está cambiando demasiado rápido para la IA

Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.

India me está pateando el culo

India me está pateando el culo

Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

¿Merrick Garland le ha fallado a Estados Unidos?

Es más de la mitad de la presidencia de Biden. ¿Qué está esperando Merrick Garland?

¿Merrick Garland le ha fallado a Estados Unidos?

Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.

Language