Dokładny język używany w specyfikacji Single UNIX do opisania znaczeniaset -e
to:
Gdy ta opcja jest włączona, jeśli proste polecenie nie powiedzie się z jednego z powodów wymienionych w Konsekwencjach błędów powłoki lub zwróci wartość statusu wyjścia> 0 i nie jest [poleceniem warunkowym lub negowanym], wówczas powłoka natychmiast się kończy.
Nie wiadomo, co się stanie, gdy takie polecenie pojawi się w podpowłoce . Z praktycznego punktu widzenia wszystko, co może zrobić podpowłoka, to wyjść i zwrócić niezerowy stan powłoki nadrzędnej. To, czy powłoka nadrzędna z kolei zakończy działanie, zależy od tego, czy ten niezerowy status przekłada się na proste polecenie, które zawodzi w powłoce nadrzędnej.
Jednym z takich problematycznych przypadków jest przypadek, który napotkałeś: niezerowy status powrotu z podstawienia polecenia . Ponieważ ten status jest ignorowany, nie powoduje to zamknięcia powłoki nadrzędnej. Jak już odkryłeś , sposobem wzięcia pod uwagę statusu wyjścia jest użycie podstawienia polecenia w prostym przydziale : wtedy stanem wyjścia przypisania jest status wyjścia ostatniego podstawienia polecenia w przypisaniu (-ach) .
Zauważ, że będzie to działało zgodnie z przeznaczeniem tylko wtedy, gdy istnieje podstawienie pojedynczego polecenia, ponieważ brany jest pod uwagę tylko status ostatniego zastąpienia. Na przykład następujące polecenie jest skuteczne (zarówno zgodnie ze standardem, jak i w każdej implementacji, jaką widziałem):
a=$(false)$(echo foo)
Innym przypadkiem jest, aby obserwować wyraźne podpowłok : (somecommand)
. Zgodnie z powyższą interpretacją podpowłoka może zwrócić niezerowy status, ale ponieważ nie jest to proste polecenie w powłoce nadrzędnej, powłoka nadrzędna powinna kontynuować. W rzeczywistości wszystkie znane mi powłoki powodują, że rodzic powraca w tym momencie. Chociaż jest to przydatne w wielu przypadkach, na przykład gdy (cd /some/dir && somecommand)
nawiasy są używane do utrzymania operacji takiej jak bieżąca zmiana katalogu lokalnego, narusza specyfikację, jeśli set -e
jest wyłączona w podpowłoce lub jeśli podpowłoka zwraca niezerowy status w sposób, który nie zakończyłby go, na przykład używając !
prawdziwego polecenia. Na przykład wszystkie programy ash, bash, pdksh, ksh93 i zsh wychodzą bez wyświetlania foo
w następujących przykładach:
set -e; (set +e; false); echo "This should be displayed"
set -e; (! true); echo "This should be displayed"
Jednak żadne proste polecenie nie zadziałało, dopóki nie set -e
działało!
Trzecim problematycznym przypadkiem są elementy niebanalnego rurociągu . W praktyce wszystkie powłoki ignorują awarie elementów rurociągu innych niż ostatni i wykazują jedno z dwóch zachowań dotyczących ostatniego elementu rurociągu:
- ATT ksh i zsh, które wykonują ostatni element potoku w powłoce nadrzędnej, działają w zwykły sposób: jeśli proste polecenie zawiedzie w ostatnim elemencie potoku, powłoka wykonująca to polecenie, która okazuje się być powłoką nadrzędną, wychodzi
- Inne powłoki aproksymują zachowanie, wychodząc, jeśli ostatni element potoku zwraca niezerowy status.
Tak jak poprzednio, wyłączenie set -e
lub użycie negacji w ostatnim elemencie potoku powoduje, że zwraca niezerowy status w sposób, który nie powinien kończyć powłoki; powłoki inne niż ATT ksh i zsh zostaną wtedy zamknięte.
pipefail
Opcja Bash powoduje natychmiastowe wyjście potoku pod, set -e
jeśli którykolwiek z jego elementów zwraca niezerowy status.
Zauważ, że jako kolejna komplikacja, bash wyłącza się set -e
w podpowłokach, chyba że jest w trybie POSIX ( set -o posix
lub znajduje się POSIXLY_CORRECT
w środowisku, gdy zaczyna się bash).
Wszystko to pokazuje, że specyfikacja POSIX niestety źle radzi sobie z określeniem -e
opcji. Na szczęście istniejące powłoki są w większości spójne w swoim zachowaniu.