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.