¿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
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 $? )&
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.set -e
es la única forma que conozco de hacerlo.set -e
essleep
(break
siendo un elemento incorporado especial haría que el script saliera en caso de falla en la mayoría de los shells, comandos enif
o a la izquierda de&&
no se ven afectados porset -e
,n=...
podría fallar sin
es de solo lectura, pero eso saldría del script sinset -e
también), de modo que la interpretación suena bastante improbable. Estoy de acuerdo en que la pregunta está mal redactada.