Skrypt Bash z `set -e` nie zatrzymuje się na komendzie` ... && ... `

14

Używam set -edo zatrzymania skryptu bash przy pierwszym błędzie .

Wszystko działa OK, chyba że użyję polecenia z &&:

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

w porównaniu z:

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

Pierwszy przykład wciąż się powtarza I'm running!, ale drugi nie. Dlaczego zachowują się inaczej?

UPD. Podobne pytanie: /programming/6930295/set-e-and-short-tests

907th
źródło
Czego oczekujesz w pierwszym przykładzie?
Flup
@Flup Spodziewam się, że skrypt się zatrzyma po nieudanym cdpoleceniu
907.
1
Zobacz BashFAQ # 105, aby uzyskać ogólne omówienie miejsc, w których set -ezachowanie jest zaskakujące.
Charles Duffy,
powiązane: stackoverflow.com/questions/25794905/…
Ciro Santilli 31 改造 中心 法轮功 六四 事件

Odpowiedzi:

10

Jest to udokumentowane zachowanie. (1) Strona bash człowiek mówi, dla set -e,

Powłoka nie kończy działania, jeśli polecenie, które się nie powiedzie, znajduje się na liście poleceń bezpośrednio po słowie kluczowym whilelub until, części testu po słowach zastrzeżonych iflub elifzastrzeżonych, części dowolnego polecenia wykonanego na liście &&lub|| z wyjątkiem polecenia następującego po ostatnim &&lub|| dowolnym polecenie w potoku, ale ostatnie, lub jeśli wartość zwracana polecenia jest odwracana za pomocą !.
[Podkreślenie dodane.]

A specyfikacja języka poleceń powłoki POSIX potwierdza, że ​​jest to prawidłowe zachowanie:

-eUstawienie powinno być ignorowane podczas wykonywania listę związek po while, until, iflub elifzarezerwowanym słowem, rurociąg poczynając !zarezerwowanym słowem, lub dowolne polecenie o I-OR listy inny niż ostatnio.

oraz Sekcja 2.9.3. Definicje list tego dokumentu

Lista AND-OR jest sekwencją jednego lub więcej potoków oddzielonych operatorami „ &&” i „ ||”.

G-Man mówi „Przywróć Monikę”
źródło
9

Ta set -eopcja nie działa w niektórych sytuacjach, a jest to standardowe zachowanie i przenośność w powłoce zgodnej z POSIX.


Nieudane polecenie jest częścią potoku:

false | true; echo printed

wydrukuje printed.

I brana jest pod uwagę tylko awaria samego rurociągu:

true | false; echo 'not printed'

nic nie wydrukuje.


Nieudany run komenda w liście złożonych po while, until, if, elifsłowa zastrzeżonego, rurociąg poczynając !zarezerwowanym słowem, ani jako część polecenia &&lub ||listy wyjątkiem ostatniego:

false || true; echo printed

Ostatnie niepowodzenie polecenia nadal set -ewpływa na:

true && false; echo 'not printed'

Powłoki w tle nie w poleceniu związku:

(false; echo 'not printed') | cat -; echo printed
Cuonglm
źródło
Dziękuję Ci! Byłoby łatwiejsze w użyciu echo "printed"i echo "not_printed"w twoich przykładach (zamiast echo 1).
907
3
Zauważ, że set -epowoduje wyjście w (false && true); echo not here, ale nie w { false && true; }; echo here, chociaż YMMV z różnymi powłokami, a nawet różnymi wersjami tej samej powłoki. Nie set -edotknąłbym tyczką i zamiast tego wykonałbym właściwą obsługę błędów.
Stéphane Chazelas
1

zgaduję, że warunek „jeśli-to” oceniam jako prawdziwy.

próbowałem

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

kto daje

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

kod błędu jest przechwytywany przez warunek, więc bash nie spowoduje zakończenia wykonywania.

Archemar
źródło
Ale nie używamif ... fi
907
Wiem, że jest to domniemane, jeśli.
Archemar