To pytanie pojawiło się w quizie przed wywiadem i doprowadza mnie do szału. Czy ktoś może odpowiedzieć na to i uspokoić mnie? Quiz nie ma odniesienia do konkretnej powłoki, ale opis zadania dotyczy unixa sa. znowu pytanie jest po prostu ...
Co robi „set –e” i dlaczego można go uznać za niebezpieczny?
Odpowiedzi:
set -e
powoduje zamknięcie powłoki, jeśli jakakolwiek komenda lub potok zwraca status niezerowy.Odpowiedź, której prawdopodobnie szukał ankieter, to:
From http://www.debian.org/doc/debian-policy/ch-opersys.html 9.3.2 -
To ważne pytanie z punktu widzenia ankietera, ponieważ ocenia kandydatów pod kątem znajomości skryptów i automatyzacji na poziomie serwera
źródło
Od
bash(1)
:Niestety nie jestem wystarczająco kreatywny, aby wymyślić, dlaczego byłoby to niebezpieczne, poza tym, że „reszta skryptu nie zostanie wykonana” lub „być może może maskować prawdziwe problemy”.
źródło
set
! Zawsze kończę nabuiltin(1)
. Dzięki.set
należy znaleźć dokumentacjęman 1 bash
? i jak ktokolwiek mógłby znaleźć-e
opcjęset
słowa kluczowego na tak ogromnej stronie podręcznika? nie możesz po prostu/-e
tutaj szukaćhelp set
Należy zauważyć, że
set -e
można go włączać i wyłączać dla różnych sekcji skryptu. Nie musi być włączony podczas wykonywania całego skryptu. Może być nawet warunkowo włączony. To powiedziawszy, nigdy go nie używam, ponieważ wykonuję własną obsługę błędów (lub nie).Na uwagę zasługuje również sekcja strony podręcznika użytkownika Bash na
trap
komendzie, która opisuje również sposóbset -e
działania w określonych okolicznościach.Istnieją więc pewne warunki, w których stan niezerowy nie spowoduje wyjścia.
Wydaje mi się, że niebezpieczeństwem jest niezrozumienie, kiedy
set -e
wchodzi w grę, a kiedy nie, i poleganie na nim niepoprawnie przy niewłaściwych założeniach.Zobacz także BashFAQ / 105 Dlaczego nie ustawiam -e (lub ustawia -o errexit lub pułapkę ERR) zgodnie z oczekiwaniami?
źródło
Pamiętaj, że jest to quiz na rozmowę kwalifikacyjną. Pytania mogły zostać napisane przez obecnych pracowników i mogą być błędne. Niekoniecznie jest to złe i wszyscy popełniają błędy, a pytania podczas wywiadu często siedzą w ciemnym kącie bez recenzji i pojawiają się tylko podczas wywiadu.
Jest całkiem możliwe, że „zestaw -e” nie robi nic, co uważalibyśmy za „niebezpieczne”. Ale autor tego pytania może błędnie uwierzyć, że „zestaw -e” jest niebezpieczny z powodu własnej ignorancji lub stronniczości. Może napisali błędny skrypt powłoki, bombardowali go okropnie i błędnie myśleli, że winny był „zestaw -e”, podczas gdy w rzeczywistości zaniedbali napisania właściwego sprawdzania błędów.
W ciągu ostatnich 2 lat uczestniczyłem prawdopodobnie w 40 rozmowach o pracę, a ankieterzy czasami zadają pytania, które są złe lub mają błędne odpowiedzi.
A może to podchwytliwe pytanie, które byłoby kiepskie, ale nie do końca nieoczekiwane.
A może to dobre wytłumaczenie: http://www.mail-archive.com/[email protected]/msg473314.html
źródło
set -e
nakazuje bashowi, w skrypcie, aby zakończył działanie, gdy cokolwiek zwróci niezerową wartość zwracaną.widziałem, jak to byłoby denerwujące i buggy, nie jestem pewien co do niebezpieczeństwa, chyba że otworzysz uprawnienia do czegoś, a zanim będziesz mógł je ponownie ograniczyć, twój skrypt umarł.
źródło
set -e
w rzeczywistości dla mnie mówi się o lenistwie, aby zignorować sprawdzanie błędów w swoich skryptach ... więc miej to na uwadze, również z tym pracodawcą ... jeśli go używają bardzo, jak wyglądają ich skrypty, które nieuchronnie będziesz musiał utrzymywać ...set -e
kończy skrypt, jeśli napotkany zostanie niezerowy kod wyjścia, poza pewnymi warunkami. Podsumowując niebezpieczeństwa związane z jego użyciem w kilku słowach: nie zachowuje się tak, jak ludzie myślą.Moim zdaniem należy go traktować jako niebezpieczny hack, który nadal istnieje wyłącznie w celach kompatybilności.
set -e
Oświadczenie nie włącza powłokę z języka, który wykorzystuje kody błędów na język, który wykorzystuje przepływ sterowania wyjątku podobny, to jedynie słabo próbuje naśladować to zachowanie.Greg Wooledge ma wiele do powiedzenia na temat zagrożeń związanych z
set -e
:set -e
)W drugim linku znajdują się różne przykłady nieintuicyjnego i nieprzewidywalnego zachowania
set -e
.Niektóre przykłady nieintuicyjnego zachowania
set -e
(niektóre z powyższego linku wiki):let x++
zwraca 0, które jest traktowane przezlet
słowo kluczowe jako wartość fałszowania i zamieniane w niezerowy kod wyjścia.set -e
zauważa to i cicho kończy skrypt.Powyższe działa zgodnie z oczekiwaniami, drukując ostrzeżenie, jeśli
/opt/foo
już istnieje.Powyższe, pomimo że jedyną różnicą jest to, że pojedyncza linia została przekształcona w funkcję, zakończy się, jeśli
/opt/foo
nie istnieje. Wynika to z faktu, że fakt, że działał pierwotnie, stanowi wyjątek odset -e
zachowania. Gdya && b
zwraca wartość niezerową, jest ignorowana przezset -e
. Jednak teraz, gdy jest to funkcja, kod wyjścia funkcji jest równy kodowi wyjścia tej komendy, a funkcja zwracająca wartość niezerową po cichu zakończy skrypt.Powyższe przeczyta tablicę
config_vars
z plikuconfig
. Jak autor może chcieć, kończy się z błędem, jeśli goconfig
brakuje. Ponieważ autor może nie zamierzać, po cichu kończy, jeśliconfig
nie kończy się na nowej linii. Gdybyset -e
nie były tu użyte, wówczasconfig_vars
zawierałyby wszystkie wiersze pliku, niezależnie od tego, czy zakończyły się one nową linią.Użytkownicy Sublime Text (i innych edytorów tekstu, które nieprawidłowo obsługują znaki nowej linii), wystrzegają się.
Tutaj autor może zasadnie oczekiwać, że jeśli z jakiegoś powodu użytkownik
$user
nie istnieje,groups
polecenie zakończy się niepowodzeniem, a skrypt zostanie zakończony, a użytkownik nie będzie mógł wykonać jakiegoś zadania bez kontroli. Jednak w tym przypadkuset -e
wypowiedzenie nigdy nie obowiązuje. Jeśli$user
z jakiegoś powodu nie można go znaleźć, zamiast zakończyć skrypt,should_audit_user
funkcja zwróci niepoprawne dane, jakbyset -e
nie działało.Dotyczy to każdej funkcji wywoływanej z części warunku
if
instrukcji, bez względu na to, jak głęboko jest zagnieżdżona, bez względu na to, gdzie jest zdefiniowana, bez względu na to, czy uruchomiszset -e
ją ponownie. Użycieif
w dowolnym momencie całkowicie wyłącza efekt doset -e
momentu pełnego wykonania bloku warunków. Jeśli autor nie jest świadomy tego pułapki lub nie zna całego stosu wywołań we wszystkich możliwych sytuacjach, w których można wywołać funkcję, wówczas napisze kod błędu i dostarczone fałszywe poczucie bezpieczeństwaset -e
będzie przynajmniej częściowo winić.Nawet jeśli autor jest w pełni świadomy tego pułapki, obejście polega na napisaniu kodu w taki sam sposób, w jaki napisano by go bez
set -e
, skutecznie czyniąc ten przełącznik mniej niż bezużytecznym; autor musi nie tylko napisać ręczny kod obsługi błędów, jakbyset -e
nie obowiązywał, ale obecnośćset -e
może go oszukać, że nie muszą.Niektóre dalsze wady
set -e
:let x++
powyżej nie ma to miejsca. Jeśli skrypt niespodziewanie umiera nieoczekiwanie, zwykle jest cichy, co utrudnia debugowanie. Jeśli skrypt nie umiera, a spodziewałeś się tego (patrz poprzedni punkt), masz na rękach bardziej subtelny i podstępny błąd.if
warunek-punkt.set -e
różnych wersjach.set -e
jest kwestią sporną, a niektórzy zdają sobie sprawę z otaczających go problemów, którzy go zalecają, podczas gdy inni zalecają ostrożność, gdy jest aktywny, aby poznać pułapki. Jest wielu początkujących skryptów powłoki, którzy polecająset -e
wszystkie skrypty jako uniwersalne rozwiązanie w przypadku błędów, ale w rzeczywistości tak nie działa.set -e
nie zastąpi edukacji.źródło
Powiedziałbym, że to niebezpieczne, ponieważ nie kontrolujesz już, jak przebiega twój skrypt. Skrypt może zostać zakończony, o ile dowolne z poleceń wywoływanych przez skrypt zwraca wartość niezerową. Więc wszystko, co musisz zrobić, to zrobić coś, co zmieni zachowanie lub dane wyjściowe któregokolwiek ze składników, i możesz zakończyć główny skrypt. Może to być bardziej problem ze stylem, ale na pewno ma konsekwencje. Co jeśli ten twój główny skrypt powinien ustawić flagę, a tak się nie stało, ponieważ zakończył się wcześnie? Skończyłbyś z resztą systemu, jeśli zakłada, że flaga powinna tam być, lub pracuje z nieoczekiwaną wartością domyślną lub starą.
źródło
Jako bardziej konkretny przykład odpowiedzi @ Marcina, która osobiście mnie ugryzła, wyobraź sobie, że
rm foo/bar.txt
gdzieś w twoim skrypcie była linia. Zwykle nic wielkiego, jeślifoo/bar.txt
tak naprawdę nie istnieje. Jednak zset -e
obecnym teraz twój skrypt skończy się tam wcześnie! Upsźródło