użycie zestawu -u nie działa zgodnie z oczekiwaniami

12

Uczę się, jak efektywnie korzystać z różnych setopcji w moim skrypcie i natknąłem się na to, set -uże wydaje się idealny do wychodzenia ze skryptu, jeśli zmienna nie zostanie poprawnie ustawiona (np. Usuwanie użytkowników). Według mężczyzny stronie, set -ui set -erobi, co następuje ...

-e  Exit immediately if a command exits with a non-zero status.
-u  Treat unset variables as an error when substituting.

Utworzyłem skrypt testowy, aby przetestować tę funkcjonalność, ale wydaje się, że nie działa zgodnie z oczekiwaniami. Być może ktoś mógłby mi lepiej wyjaśnić mój problem i gdzie źle interpretuję? Skrypt testowy znajduje się poniżej. Dziękuję Ci.

set -e
set -u
testing="This works"
echo $?
echo ${testing}
testing2=
echo $?
echo ${testing2}
testing3="This should not appear"
echo $?
echo ${testing3}

Oczekuję, że skrypt wyświetli 0 i „To działa” , a następnie zakończy się niepowodzeniem, ponieważ ${testing2}nie jest ustawiony.

Zamiast tego wyświetla się 0 i „To działa” , następnie 0, a następnie 0 To nie powinno się pojawić

Czy ktoś może podać trochę wiedzy? Dziękuję Ci.

Azifor
źródło
1
Więc kontynuacja ... czy jest jakiś sposób, aby ustawić zmienną na łańcuch zerowy jako nielegalną / zgłosić błąd? Chyba nie.
Luke Davis,

Odpowiedzi:

10

Z „man Bash”:

Parametr jest ustawiany, jeśli przypisano mu wartość. Ciąg zerowy jest prawidłową wartością. Po ustawieniu zmiennej można ją rozbroić tylko za pomocą wbudowanej komendy unset.

Kiedy to robisz testing2=, ustawiasz zmienną na ciąg pusty.

Zmień to na unset testing2i spróbuj ponownie.


W set -etym przypadku nie pomaga, ponieważ przypisanie nigdy nie ma kodu wyjścia 1. Spróbuj tego, aby zobaczyć, że ostatnie wykonane polecenie (przypisanie) ma kod wyjścia 0, lub przeczytaj to pytanie :

$ false; a=""; echo $?
0

I wierzę również, że użycie zestawu -e jest bardziej problemem niż rozwiązaniem.

Błąd, który może wystąpić przy użyciu nieuzbrojonych zmiennych, to set -u:

#!/bin/bash
set -u
testing="This works"
echo ${testing}
unset testing2
echo ${testing2}
testing3="This should not appear"
echo ${testing3}

Wyjdzie:

$  ./script.sh
This works
./script.sh: line 9: testing2: unbound variable
Społeczność
źródło
3

testing2=ustawia testing2zmienną na pusty ciąg; zmienna faktycznie jest ustawiona .

Jednak jeśli miałbyś działać echo $testing99w interaktywnej powłoce Bash (bez ustawiania errexit, tj. set -e), Pojawiłby się błąd:

bash: testing99: unbound variable

Na bok

Podczas testowania skryptów właśnie odkryłem, że powłoka interaktywna nie zawsze kończy działanie, gdy próbuje rozwinąć zmienną, która nie została ustawiona, podczas gdy powłoka nieinteraktywna (uruchamiająca skrypt powłoki) zawsze wychodzi . Według strony podręcznika POSIX dla set:

-u Powłoka powinna napisać komunikat do standardowego błędu, gdy próbuje rozwinąć zmienną, która nie jest ustawiona, i natychmiast kończy działanie. Powłoka interaktywna nie może wyjść.

Interaktywna powłoka Bash nie zostanie zakończona, chyba że errexitzostała również ustawiona. Z drugiej strony interaktywna powłoka deski rozdzielczej nie zostanie zamknięta - nawet jeśli set -ewcześniej była uruchomiona.

Anthony Geoghegan
źródło
Jeśli myślnik nie kończy działania z ustawieniem -e; set u; rozbroić aa; echo $ aa, następnie myślnik jest zły.
schily
@schily Kiedy to zauważyłem, doszedłem do wniosku, że autorzy myślników znają się lepiej ode mnie i że w specyfikacji POSIX może istnieć pewna dwuznaczność, ale po ponownym sprawdzeniu pubs.opengroup.org/onlinepubs/9699919799/utilities/... , ja zgadzam się, że to wygląda na błąd, w porządku.
Anthony Geoghegan
Istnieje prosta zasada: gdy zarówno Korn Shell, jak i Bourne Shell zgadzają się, a inna implementacja powłoki ma odchylenie, wówczas druga powłoka zachowuje się nieprawidłowo.
schily,