Badam zawartość tego pliku preinst , który skrypt wykonuje przed rozpakowaniem pakietu z pliku archiwum Debiana (.deb).
Skrypt ma następujący kod:
#!/bin/bash
set -e
# Automatically added by dh_installinit
if [ "$1" = install ]; then
if [ -d /usr/share/MyApplicationName ]; then
echo "MyApplicationName is just installed"
return 1
fi
rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf
rm -Rf $HOME/.local/share/file-manager/actions/*
fi
# End automatically added section
Moje pierwsze zapytanie dotyczy linii:
set -e
Myślę, że reszta skryptu jest dość prosta: sprawdza, czy menedżer pakietów Debian / Ubuntu wykonuje operację instalacji. Jeśli tak, sprawdza, czy moja aplikacja została właśnie zainstalowana w systemie. Jeśli tak, skrypt wypisuje komunikat „MyApplicationName jest właśnie zainstalowany” i kończy się ( return 1
oznacza to, że kończy się na „błędzie”, prawda?).
Jeśli użytkownik prosi system pakietów Debian / Ubuntu o zainstalowanie mojego pakietu, skrypt usuwa również dwa katalogi.
Czy to prawda, czy coś mi brakuje?
man set
set +e
Odpowiedzi:
Od
help set
:Ale jest to uważane przez niektórych za złą praktykę (autorzy FAQ bash i irc freenode #bash FAQ). Zaleca się stosowanie:
uruchomić
do_something
funkcję, gdy wystąpią błędy.Zobacz http://mywiki.wooledge.org/BashFAQ/105
źródło
trap 'exit' ERR
ERR
Pułapka nie jest dziedziczona przez funkcje powłoki, więc jeśli masz funkcje,set -o errtrace
lubset -E
pozwoli Ci ustawić pułapkę tylko raz i stosuje się go na całym świecie.trap 'exit' ERR
zrobić cokolwiek różni się odset -e
?set -e
zatrzymuje wykonywanie skryptu, jeśli polecenie lub potok zawiera błąd - co jest przeciwieństwem domyślnego zachowania powłoki, które polega na ignorowaniu błędów w skryptach. Wpiszhelp set
terminal, aby wyświetlić dokumentację tego wbudowanego polecenia.źródło
set -o pipefail
której można użyć do propagowania błędów, tak aby zwracana wartość polecenia potoku była niezerowa, jeśli jedno z poprzednich poleceń zakończyło się z niezerowym statusem.-o pipefail
oznacza to tylko, że status wyjścia pierwszego niezerowego (tzn. Błędnego pod-o errexit
względem warunku ) polecenia potoku jest propagowany do końca. Pozostałe polecenia w potoku nadal działają , nawet zset -o errexit
. Na przykładecho success | cat - <(echo piping); echo continues
, gdzieecho success
reprezentuje udane, ale polecenie omylny, będzie drukowaćsuccess
,piping
icontinues
, alefalse | cat - <(echo piping); echo continues
, zefalse
reprezentujący komendę teraz erroring cicho, nadal będzie drukowaćpiping
przed wyjściem.Zgodnie bash - zestaw Wbudowane instrukcji, jeśli
-e
/errexit
jest ustawiony, wychodzi powłoki natychmiast jeśli rurociąg składający się z jednego prostego polecenia , listy lub związek dowodzenia zwraca stan niezerowe.Domyślnie stanem wyjścia potoku jest status wyjścia ostatniego polecenia w potoku, chyba że
pipefail
opcja jest włączona (domyślnie jest wyłączona).Jeśli tak, to zwracany przez potok status ostatniego (najbardziej na prawo) polecenia do wyjścia ze stanem niezerowym lub zero, jeśli wszystkie polecenia zakończą się pomyślnie.
Jeśli chcesz wykonać coś przy wyjściu, spróbuj zdefiniować
trap
, na przykład:gdzie
onexit
jest twoja funkcja do zrobienia czegoś przy wyjściu, na przykład poniżej, który drukuje prosty ślad stosu :Istnieje podobna opcja
-E
/errtrace
która zamiast tego pułapkowałaby na ERR, np .:Przykłady
Przykład statusu zerowego:
Przykład niezerowego statusu:
Przykłady negujące status:
Test z
pipefail
wyłączeniem:Test z
pipefail
włączonym:źródło
Znalazłem ten post, próbując dowiedzieć się, jaki był status wyjścia skryptu, który został przerwany z powodu
set -e
. Odpowiedź nie wydawała mi się oczywista; stąd ta odpowiedź. Zasadniczoset -e
przerywa wykonywanie polecenia (np. Skrypt powłoki) i zwraca kod statusu wyjścia polecenia, które się nie powiodło (tj. Wewnętrzny skrypt, a nie zewnętrzny skrypt) .Załóżmy na przykład, że mam skrypt powłoki
outer-test.sh
:Kod dla
inner-test.sh
:Kiedy uruchamiam
outer-script.sh
z linii poleceń, mój skrypt zewnętrzny kończy się kodem wyjścia skryptu wewnętrznego:źródło
Uważam, że chodzi o to, aby dany skrypt szybko zawodził.
Aby przetestować to sam, po prostu wpisz
set -e
polecenie bash. Teraz spróbuj uruchomićls
. Otrzymasz listę katalogów. Teraz wpiszlsd
. To polecenie nie zostało rozpoznane i zwróci kod błędu, więc monit bash zostanie zamknięty (z powoduset -e
).Teraz, aby zrozumieć to w kontekście „skryptu”, użyj tego prostego skryptu:
Jeśli uruchomisz go tak, jak jest, otrzymasz listę katalogów z
ls
ostatniego wiersza. Jeśli odkomentujeszset -e
i uruchom ponownie, nie zobaczysz listy katalogów, ponieważ bash przestaje przetwarzać, gdy napotka błądlsd
.źródło
To stare pytanie, ale żadna z odpowiedzi tutaj nie omawia użycia
set -e
akaset -o errexit
w skryptach obsługujących pakiety Debiana. Użycie tej opcji jest obowiązkowe w tych skryptach, zgodnie z polityką Debiana; celem jest najwyraźniej uniknięcie jakiejkolwiek możliwości wystąpienia nieobsługiwanego błędu.W praktyce oznacza to, że musisz zrozumieć, w jakich warunkach uruchomione polecenia mogą zwrócić błąd i obsłużyć każdy z tych błędów jawnie.
Typowe gotchas to np.
diff
(Zwraca błąd, gdy występuje różnica) igrep
(zwraca błąd, gdy nie ma zgodności). Możesz uniknąć błędów dzięki jawnej obsłudze:(Zwróć też uwagę, jak staramy się zawrzeć w komunikacie nazwę bieżącego skryptu i pisać komunikaty diagnostyczne na standardowy błąd zamiast na standardowe wyjście).
Jeśli żadna jawna obsługa nie jest naprawdę konieczna ani użyteczna, jawnie nic nie rób:
(Użycie
:
polecenia no-op powłoki jest nieco niejasne, ale dość powszechne).Powtarzam,
jest skrótem od
tzn. wyraźnie mówimy, że
other
powinien być uruchamiany tylko wtedy, gdy sięsomething
nie powiedzie. Długaif
(i inne instrukcje kontroli przepływu w powłoce, takie jakwhile
,until
) jest również prawidłowym sposobem obsługi błędu (w rzeczywistości, gdyby tak nie było, skrypty powłoki zset -e
nigdy nie mogłyby zawierać instrukcji kontroli przepływu!)A także, mówiąc wprost, w przypadku braku takiego programu obsługi,
set -e
cały skrypt natychmiast przestanie działać z błędem, jeślidiff
znajdzie różnicę lubgrep
nie znajdzie dopasowania.Z drugiej strony niektóre polecenia nie generują błędu wyjścia, gdy tego chcesz. Powszechnie problematycznymi poleceniami są
find
(status wyjścia nie odzwierciedla, czy pliki zostały faktycznie znalezione) ised
(status wyjścia nie ujawni, czy skrypt otrzymał jakieś dane wejściowe, czy też faktycznie wykonał jakiekolwiek polecenia). Prostą ochroną w niektórych scenariuszach jest potokowanie do polecenia, które krzyczy, jeśli nie ma wyjścia:Należy zauważyć, że stanem wyjścia potoku jest status wyjścia ostatniego polecenia w tym potoku. Tak więc powyższe polecenia faktycznie całkowicie maskują status
find
ised
i mówią tylko, czy wgrep
końcu się udało.(Bash oczywiście ma
set -o pipefail
; ale skrypty pakietów Debiana nie mogą korzystać z funkcji Bash. Polityka zdecydowanie dyktuje użycie POSIXsh
dla tych skryptów, chociaż nie zawsze tak było.)W wielu sytuacjach jest to coś, na co należy uważać przy defensywnym kodowaniu. Czasami trzeba np. Przejść przez plik tymczasowy, aby zobaczyć, czy polecenie, które wytworzyło to wyjście, zakończyło się powodzeniem, nawet jeśli idiom i wygoda w przeciwnym razie skierowałyby cię do korzystania z potoku powłoki.
źródło
źródło