¿Abortar un script de shell si algún comando devuelve un valor distinto de cero?

Tengo un script de shell Bash que invoca una cantidad de comandos. Me gustaría que el script de shell salga automáticamente con un valor de retorno de 1 si alguno de los comandos devuelve un valor distinto de cero.

¿Es esto posible sin verificar explícitamente el resultado de cada comando?

p.ej

dosomething1 if [[ $? -ne 0 ]]; then exit 1 fi dosomething2 if [[ $? -ne 0 ]]; then exit 1 fi 

Agregue esto al comienzo del script:

 set -e 

Esto hará que el shell salga inmediatamente si sale un comando simple con un valor de salida distinto de cero. Un comando simple es cualquier comando que no forme parte de un if, while o hasta la prueba, o parte de un && o || lista.

Consulte la página man de bash (1) en el comando interno “establecer” para obtener más detalles.

Personalmente, comienzo casi todos los scripts de shell con “set -e”. Es realmente molesto tener una secuencia de comandos obstinada cuando algo falla en el medio y rompe las suposiciones para el rest del guión.

Para agregar a la respuesta aceptada:

Tenga en cuenta que set -e veces no es suficiente, especialmente si tiene tuberías.

Por ejemplo, supongamos que tiene este script

 #!/bin/bash set -e ./configure > configure.log make 

… que funciona como se esperaba: un error en la configure anula la ejecución.

Mañana harás un cambio aparentemente trivial:

 #!/bin/bash set -e ./configure | tee configure.log make 

… y ahora no funciona. Esto se explica aquí , y se proporciona una solución (solo Bash):

 #! / bin / bash
 set -e 
 establecer -o pipefail

 ./configure |  tee configure.log
 hacer

Las declaraciones if en tu ejemplo son innecesarias. Solo hazlo así:

 dosomething1 || exit 1 

Si toma los consejos de Ville Laurikari y usa set -e luego para algunos comandos, puede necesitar usar esto:

 dosomething || true 

El || true || true hará que el canal de comando tenga un true valor de retorno incluso si el comando falla, por lo que la opción -e no matará el script.

Si tiene que hacer una limpieza al salir, también puede usar ‘trap’ con el ERR de pseudo-señal. Esto funciona de la misma manera que capturando INT o cualquier otra señal; bash arroja ERR si algún comando sale con un valor distinto de cero:

 # Create the trap with # trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...] trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM command1 command2 command3 # Partially turn off the trap. trap - ERR # Now a control-C will still cause cleanup, but # a nonzero exit code won't: ps aux | grep blahblahblah 

O, especialmente si está utilizando “set -e”, podría atrapar EXIT; su trampa se ejecutará cuando el script se cierre por cualquier razón, incluyendo un final normal, interrupciones, una salida causada por la opción -e, etc.

Ejecútelo con -e o set -e en la parte superior.

También mira el set -u .

¿El $? variable rara vez es necesaria. El command; if [ $? -eq 0 ]; then X; fi pseudo-idiom command; if [ $? -eq 0 ]; then X; fi command; if [ $? -eq 0 ]; then X; fi command; if [ $? -eq 0 ]; then X; fi siempre debe escribirse como if command; then X; fi if command; then X; fi if command; then X; fi .

Los casos donde $? es obligatorio cuando se debe verificar contra múltiples valores:

 command case $? in (0) X;; (1) Y;; (2) Z;; esac 

o cuando $? necesita ser reutilizado o manipulado de otra manera:

 if command; then echo "command successful" >&2 else ret=$? echo "command failed with exit code $ret" >&2 exit $ret fi 

Una expresión como

 dosomething1 && dosomething2 && dosomething3 

dejará de procesarse cuando uno de los comandos vuelva con un valor distinto de cero. Por ejemplo, el siguiente comando nunca imprimirá “hecho”:

 cat nosuchfile && echo "done" echo $? 1 
 #!/bin/bash -e 

debería ser suficiente.

simplemente lanzando en otro para referencia ya que había una pregunta adicional a la entrada de Mark Edgars y aquí hay un ejemplo adicional y toca el tema en general:

 [[ `cmd` ]] && echo success_else_silence 

que es lo mismo que cmd || exit errcode cmd || exit errcode como alguien mostró.

p.ej. Quiero asegurarme de que una partición esté desmontada si está montada:

 [[ `mount | grep /dev/sda1` ]] && umount /dev/sda1