scripts script resueltos programacion pasar parametros operaciones manejo español ejercicios ejemplos comandos cadenas aritmeticas linux bash unix shell

programacion - scripts linux ejercicios resueltos



¿Anulando un script de shell si algún comando devuelve un valor distinto de cero? (9)

Tengo un script de shell Bash que invoca una serie 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 se cierre inmediatamente si un comando simple sale con un valor de salida distinto de cero. Un comando simple es cualquier comando que no sea parte de if, while, o hasta prueba, o parte de && o || lista.

Consulte la página del manual de bash (1) en el comando interno "set" para obtener más detalles.

Personalmente comienzo casi todos los scripts de shell con "set -e". Es realmente molesto que un script continúe obstinadamente cuando algo falla en el medio y rompe las suposiciones para el resto del script.


Ejecutar con -e o set -e en la parte superior.

También mira set -u .


El $? la variable rara vez es necesaria. El command; if [ $? -eq 0 ]; then X; fi pseudo-idiomático 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 $? se requiere cuando se debe verificar contra varios 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


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

dosomething1 || exit 1

Si sigue el consejo de Ville Laurikari y usa set -e entonces para algunos comandos puede necesitar usar esto:

dosomething || true

El || true || true hará que la canalización del comando tenga un valor de retorno true , incluso si el comando falla, por lo que la opción -e no eliminará la secuencia de comandos.


Para añadir 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 haces un cambio aparentemente trivial:

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

... y ahora no funciona. Esto se explica here , y se proporciona una solución alternativa (solo Bash):

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


Si tiene una limpieza que necesita hacer al salir, también puede usar ''trampa'' con el ERR de pseudo-señal. Esto funciona de la misma manera que la captura de INT o cualquier otra señal; bash lanza 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 interceptar EXIT; su captura se ejecutará cuando el script salga por cualquier motivo, incluido un final normal, interrupciones, una salida causada por la opción -e, etc.


Una expresión como

dosomething1 && dosomething2 && dosomething3

detendrá el procesamiento cuando uno de los comandos regrese con un valor distinto de cero. Por ejemplo, el siguiente comando nunca se imprimirá "hecho":

cat nosuchfile && echo "done" echo $? 1


solo agregue otra como referencia, ya que hubo 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


#!/bin/bash -e

debería bastar