¿Cómo salir de un script de shell si falla una parte?

¿Cómo puedo escribir un script de shell que salga, si una parte falla? Por ejemplo, si el siguiente fragmento de código falla, la secuencia de comandos debería cerrarse.

n=0 until [ $n -ge 5 ] do gksu *command* && break n=$[$n+1] sleep 3 

Responder

Un enfoque sería agregar set -e al comienzo de su script. Eso significa (de help set):

 -e Exit immediately if a command exits with a non-zero status. 

Entonces, si alguno de sus comandos falla, el script se cerrará.

Alternativamente, puede agregar declaraciones explícitas exit en los posibles puntos de falla:

command || exit 1 

Comentarios

  • Yo (y el wiki de bash ) preferiría que la gente pensara en el manejo adecuado de errores en lugar de utilizar la función set -e (rota por diseño IMO). Sin embargo, no ' realmente se aplica aquí. El OP quiere salir del script después de 5 intentos fallidos de ejecutar el comando.
  • @St é phaneChazelas Gané ' Para discutir contigo sobre si ' está roto, ' estoy seguro de que ' re correcto. Sin embargo, el OP preguntó " ¿Cómo puedo escribir un script de shell que salga, si una parte falla? ", ¿qué te hace ¿Crees que ' s acerca de salir después de 5 fallas?
  • porque no puedo ' pensar de otra manera La pregunta puede ser interpretada.
  • @St é phaneChazelas, es posible que tenga razón. Lo interpreté literalmente: ¿cómo puede salir todo el script si falla alguna parte? Y set -e es la única forma que conozco de hacerlo.
  • En ese fragmento de script, los comandos que podrían activar set -e es sleep (break siendo un elemento incorporado especial haría que el script saliera en caso de falla en la mayoría de los shells, comandos en if o a la izquierda de && no se ven afectados por set -e, n=... podría fallar si n es de solo lectura, pero eso saldría del script sin set -e también), de modo que la interpretación suena bastante improbable. Estoy de acuerdo en que la pregunta está mal redactada.

Responder

Puede salir de un script en cualquier lugar usando la palabra clave exit. También puede especificar un código de salida para indicar a otros programas que o cómo falló su script, p. Ej. exit 1 o exit 2 etc. (Por convención, el código de salida 0 es para el éxito y cualquier cosa mayor que 0 significa falla; sin embargo, también por convención , los códigos de salida por encima de 127 están reservados para terminación anormal (por ejemplo, por una señal)).

La construcción genérica para salir en caso de falla es

if [ failure condition ]; then exit n fi 

con failure condition y n adecuados. Pero en escenarios específicos, puede proceder de manera diferente. Ahora, para su caso, interpreto su pregunta de que si alguna de las cinco invocaciones de gksu falla, entonces quiere salir. Una forma es usar una función como esta

function try_command { for i in 1 2 3 4 5 ; do if gksu command ; then return 0 fi fi exit 1 } 

y luego, invocar el bucle con try_command.

Hay formas (más) avanzadas o sofisticadas de cómo abordar su pregunta. Sin embargo, la solución anterior es más accesible para los principiantes que, digamos, la solución de Stephane.

Respuesta

attempt=0 until gksu command; do attempt=$((attempt + 1)) if [ "$attempt" -gt 5 ]; then exit 1 fi done 

exit sale del script a menos que sea llamado en una subcapa. Si esa parte de la secuencia de comandos está en una subcapa, por ejemplo, porque está «dentro de (...) o $(...) o como parte de una tubería , entonces solo saldrá de ese subshell .

En ese caso, si desea que el script salga además del subshell, entonces » Necesitaré llamar a exit cuando salga esa subcapa.

Por ejemplo, aquí con 2 niveles anidados de subcapa:

( life=hard output=$( echo blah [ "$life" = easy ] || exit 1 # exit subshell echo blih not run ) || exit # if the subshell exits with a non-zero exit status, # exit as well with the same exit status echo not run either ) || exit # if the subshell exits with a non-zero exit status, # exit as well with the same exit status 

Puede resultar más complicado si la subcapa es parte de una canalización. bash tiene una matriz $PIPESTATUS especial, similar a zsh «s $pipestatus uno que puede ayudarlo aquí:

{ echo foo exit 1 echo bar } | wc -c subshell_ret=${PIPESTATUS[0]} if [ "$subshell_ret" -ne 0 ]; then exit "$subshell_ret" fi 

Respuesta

Trap realizará una acción al recibir una señal.

trap "echo EXIT; exit" 0 trap "echo HUP; exit" 1 trap "echo CTL-C; exit" 2 trap "echo QUIT; exit" 3 trap "echo ERR; exit" ERR n=0 until [ $n -ge 5 ] do n=$[$n+1] echo $n sleep 3 done 

Ejecute esto y déjelo salir normalmente. Atrapa en la señal 0.

EXIT 

Ejecútelo de nuevo e interrumpa con ^ C. Se intercepta tanto en la señal 2 como en la señal 0.

CTL-C EXIT 

Un estado de salida distinto de cero se capturará en ERR

ERR EXIT 

Respuesta

pass_to_functio() { echo "command exited with status $1" } ( exec <Any Command > & child_pid=$! wait $child_pid pass_to_function $? )& 

Deja una respuesta

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