Obserwuję dziwne zachowanie podczas używania set -e
( errexit
), set -u
( nounset
) wraz z pułapkami ERR i EXIT. Wydają się powiązane, więc postawienie ich w jednym pytaniu wydaje się rozsądne.
1) set -u
nie uruchamia pułapek ERR
Kod:
#!/bin/bash trap 'echo "ERR (rc: $?)"' ERR set -u echo ${UNSET_VAR}
- Oczekiwany: pułapka ERR zostaje wywołana, RC! = 0
- Faktycznie: pułapka ERR nie jest wywoływana, RC == 1
- Uwaga:
set -e
nie zmienia wyniku
2) Użycie set -eu
kodu wyjścia w pułapce WYJŚCIA wynosi 0 zamiast 1
Kod:
#!/bin/bash trap 'echo "EXIT (rc: $?)"' EXIT set -eu echo ${UNSET_VAR}
- Oczekiwany: wywoływana jest pułapka WYJŚCIA, RC == 1
- Faktycznie: pułapka EXIT jest wywoływana, RC == 0
- Uwaga: Podczas używania
set +e
RC == 1. Pułapka WYJŚCIA zwraca prawidłowe RC, gdy jakiekolwiek inne polecenie zgłosi błąd. - Edycja: Istnieje post SO na ten temat z interesującym komentarzem sugerującym, że może to być związane z używaną wersją Bash. Testowanie tego fragmentu w Bash 4.3.11 daje RC = 1, więc to lepiej. Niestety aktualizacja Bash (z wersji 3.2.51) na wszystkich hostach nie jest w tej chwili możliwa, dlatego musimy wymyślić inne rozwiązanie.
Czy ktoś może wyjaśnić którekolwiek z tych zachowań?
Przeszukiwanie tych tematów nie było bardzo udane, co jest dość zaskakujące, biorąc pod uwagę liczbę postów dotyczących ustawień i pułapek Basha. Jest jednak jeden wątek na forum , ale wniosek jest raczej niezadowalający.
set -e
i set -u
oba są zaprojektowane specjalnie do zabijania skryptów powłoki. Używanie ich w warunkach, które mogą uruchomić ich aplikację, zabije skryptowaną powłokę. Nie ma poruszanie się, że z wyjątkiem do nie korzystania z nich, a zamiast tego testu dla tych warunkach, gdy mają one zastosowanie w sekwencji kodu. Zasadniczo możesz napisać dobry kod powłoki lub użyć set -eu
.
-u
nie wyzwalać pułapki ERR (jest to błąd, więc nie powinien wyzwalać pułapki) lub kod błędu to 0 zamiast 1. ten drugi wydaje się być błędem, który został już naprawiony w późniejszej wersji, więc to tyle. Ale pierwsza część jest dość trudna do zrozumienia, jeśli nie zdajesz sobie sprawy, że błędy w ocenie powłoki (rozszerzenie parametrów) i rzeczywiste błędy w poleceniach wydają się być dwiema różnymi rzeczami. Jeśli chodzi o rozwiązanie, cóż, jak zasugerowałeś, staram się teraz unikać -eu
i sprawdzać ręcznie, kiedy jest to konieczne.
(set -u; : $UNSET_VAR)
i podobne. Tego rodzaju rzeczy też mogą być dobre - od &&
czasu do czasu możesz zrzucić wiele rzeczy : (set -e; mkdir dir; cd dir; touch dirfile)
jeśli dostaniesz mój dryf. Po prostu są to kontrolowane konteksty - kiedy ustawisz je jako opcje globalne, tracisz kontrolę i stajesz się kontrolowany. Zazwyczaj są jednak bardziej wydajne rozwiązania.
bash
zerwał ze standardem i zaczął umieszczać pułapki w podpowłokach. Pułapka ma być wykonana w tym samym środowisku, z którego nastąpił powrót, alebash
nie zrobiła tego od dłuższego czasu.