Lo script Bash con `set -e` non si ferma al comando` ... && ... `


13

Uso set -eper interrompere lo script bash al primo errore .

Tutto funziona bene a meno che non utilizzi il 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
$

paragonato a:

$ 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
$

Il primo esempio fa ancora eco I'm running!, ma il secondo no. Perché si comportano diversamente?

UPD. Domanda simile: /programming/6930295/set-e-and-short-tests


Cosa ti aspetti che accada nel primo esempio?
Flup,

@Flup Mi aspetto che lo script si fermi dopo un cdcomando non riuscito
907,

1
Vedi BashFAQ # 105 per una discussione generale sui luoghi in cui il set -ecomportamento è sorprendente.
Charles Duffy,

Risposte:


9

Questo è un comportamento documentato. La pagina man bash (1) dice, per set -e,

La shell non si chiude se il comando che fallisce fa parte dell'elenco dei comandi immediatamente dopo una whileo untilparola chiave, parte del test che segue le parole riservate ifo elif, parte di qualsiasi comando eseguito in una &&o ||lista tranne il comando che segue il finale &&o|| , qualsiasi comando in una pipeline ma l'ultimo, o se il valore di ritorno del comando viene invertito con !.
[Enfasi aggiunta.]

E le specifiche del linguaggio dei comandi della shell POSIX conferma che questo è il comportamento corretto:

L' -eimpostazione deve essere ignorata quando si esegue l'elenco composto seguendo il while, until, if, o elifparola riservata, un gasdotto che inizia con la !parola riservata, o qualsiasi comando di un AND-OR elenco diverso dall'ultimo.

e la Sezione 2.9.3 Elenchi di quel documento definisce

Un elenco AND-OR è una sequenza di una o più condutture separate dagli operatori " &&" e " ||".


9

L' set -eopzione non ha effetto in alcune situazioni, e questo è il comportamento standard e portatile nella shell conforme a POSIX.


Il comando non riuscito fa parte della pipeline:

false | true; echo printed

stamperà printed.

E viene considerato solo il guasto della pipeline stessa:

true | false; echo 'not printed'

non stampa nulla.


La corsa comando non riuscito nella lista composto seguendo il while, until, if, elifparola riservata, un gasdotto che inizia con la !parola riservata, o qualsiasi comando come parte di &&o ||lista tranne l'ultimo:

false || true; echo printed

L'ultimo comando non riesce ancora a set -erisentirne:

true && false; echo 'not printed'

La subshell non riesce in un comando composto:

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

Grazie! Sarebbe più chiaro da usare echo "printed"e echo "not_printed"nei tuoi esempi (anziché echo 1).
907,

3
Si noti che set -eprovoca un'uscita in (false && true); echo not here, ma non in { false && true; }; echo here, sebbene YMMV con shell diverse e persino versioni diverse di una stessa shell. Non toccherei set -econ un palo di chiatta e farei invece una corretta gestione degli errori.
Stéphane Chazelas,

1

la mia ipotesi è che la condizione if-then nel suo insieme sia vera.

Provai

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

chi dà

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

il codice di errore viene intercettato da if condition, quindi bash non attiverà la fine dell'esecuzione.


Ma non usoif ... fi
907

Lo so, questo è un implicito se.
Archemar,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.