La secuencia de comandos Bash con `set -e` no se detiene en el comando` ... && ... `


13

Yo uso set -epara detener el script bash en el primer error .

Todo funciona bien a menos que use el comando con &&:

$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$

comparado con:

$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$

El primer ejemplo todavía tiene eco I'm running!, pero el segundo no. ¿Por qué se comportan de manera diferente?

UPD Pregunta similar: /programming/6930295/set-e-and-short-tests


¿Qué esperas que pase en el primer ejemplo?
Flup

@Flup Espero que el script se detenga después de un cdcomando fallido
907th

1
Vea BashFAQ # 105 para una discusión general de lugares donde el set -ecomportamiento es sorprendente.
Charles Duffy

Respuestas:


9

Este es un comportamiento documentado. La página de manual bash (1) dice, para set -e,

El shell no sale si el comando que falla es parte de la lista de comandos que sigue inmediatamente a una palabra clave whileo until, parte de la prueba que sigue a las palabras ifo elifreservadas, parte de cualquier comando ejecutado en una lista &&o,|| excepto el comando que sigue al final &&o|| , cualquier comando en una tubería pero el último, o si se está invirtiendo el valor de retorno del comando !.
[Énfasis añadido.]

Y la especificación del lenguaje de comandos de shell POSIX confirma que este es el comportamiento correcto:

El -eajuste se tendrá en cuenta al ejecutar la lista siguiente compuesto del while, until, if, o elifpalabra reservada, una tubería que comienza con la !palabra reservada, o cualquier comando de un AND-OR de la lista que no sea la última.

y la Sección 2.9.3 Listas de ese documento define

Una lista AND-OR es una secuencia de una o más tuberías separadas por los operadores " &&" y " ||".


9

La set -eopción no tiene efecto en algunas situaciones, y este es el comportamiento estándar y portátil en el shell compatible con POSIX.


El comando fallido es parte de la tubería:

false | true; echo printed

imprimirá printed.

Y solo se considera el fracaso de la tubería en sí:

true | false; echo 'not printed'

No imprimirá nada.


La instrucción ejecutada fallado en la lista de la siguiente compuesto while, until, if, elifpalabra reservada, una tubería que comienza con la !palabra reservada, o cualquier comando como parte de &&o ||lista excepto el último:

false || true; echo printed

El último comando falla todavía set -eafecta:

true && false; echo 'not printed'

La subshell falla en un comando compuesto:

(false; echo 'not printed') | cat -; echo printed

¡Gracias! Sería más claro usarlo echo "printed"y echo "not_printed"en sus ejemplos (en lugar de echo 1).
907th

3
Tenga en cuenta que set -eprovoca una salida en (false && true); echo not here, pero no en { false && true; }; echo here, aunque YMMV con diferentes shells e incluso diferentes versiones de un mismo shell. No tocaría set -econ un poste de barcaza y en su lugar haría un manejo adecuado de los errores.
Stéphane Chazelas

1

mi suposición es si-entonces la condición en su conjunto se evalúa como verdadera.

Lo intenté

set -e
if cd not_existing_dir
then  echo 123
fi
echo "I'm running! =P"

quien da

-bash: cd: not_existing_dir: No such file or directory
I'm running! =P

el código de error es atrapado por la condición if, por lo que bash no activará el final de la ejecución.


Pero no usoif ... fi
907th

Lo sé, este es un if implícito.
Archemar
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.