Jestem notobem w skryptowaniu powłoki. Chcę wydrukować wiadomość i zakończyć skrypt, jeśli polecenie się nie powiedzie. Próbowałem:
my_command && (echo 'my_command failed; exit)
ale to nie działa. Nadal wykonuje instrukcje następujące po tym wierszu w skrypcie. Używam Ubuntu i bash.
linux
bash
exit
exitstatus
użytkownik459246
źródło
źródło
Odpowiedzi:
Próbować:
Cztery zmiany:
&&
na||
{ }
zamiast( )
;
poexit
i{
przed i przed}
Ponieważ chcesz wydrukować wiadomość i wyjść dopiero po wydaniu polecenia nie powiedzie się (kończy pracę z wartością niezerową), które potrzebują
||
nie jest&&
.uruchomi się,
cmd2
gdy sięcmd1
powiedzie (wartość wyjściowa0
). Natomiasturuchomi się,
cmd2
gdycmd1
zawiedzie (wartość wyjściowa niezerowa).Użycie
( )
powoduje, że polecenie wewnątrz nich działa w podpowłoce, a wywołanieexit
stamtąd powoduje wyjście z podpowłoki, a nie oryginalnej powłoki, dlatego wykonywanie jest kontynuowane w oryginalnej powłoce.Aby przezwyciężyć to użycie
{ }
Ostatnie dwie zmiany są wymagane przez bash.
źródło
{ (>&2 echo 'my_command failed') ; exit 1; }
Inne odpowiedzi dobrze ujęły bezpośrednie pytanie, ale możesz również być zainteresowany
set -e
. Dzięki temu każde polecenie, które się nie powiedzie (poza określonymi kontekstami, takimi jakif
testy), spowoduje przerwanie skryptu. W przypadku niektórych skryptów jest to bardzo przydatne.źródło
set -e
ma długi i tajemniczy zestaw zasad dotyczących tego, kiedy działa, a kiedy nie. (Jeśli ktoś uruchomi sięif yourfunction; then ...
,set -e
nigdy nie uruchomi się w środkuyourfunction
ani nic, co wywoła , ponieważ kod ten jest uważany za „zaznaczony”). Zobacz sekcję ćwiczeń BashFAQ # 105 , omawiając tę i inne pułapki (niektóre z nich dotyczą tylko określonych wersji powłoki, więc musisz koniecznie przetestować każdą wersję, która może być użyta do uruchomienia twojego skryptu).Zauważ też, że status wyjścia każdego polecenia jest przechowywany w zmiennej powłoki $ ?, którą możesz sprawdzić natychmiast po uruchomieniu polecenia. Niezerowy status oznacza błąd:
źródło
echo "Just finished step A"
, nie wiedząc, że toecho
nadpisało to,$?
co miało być sprawdzone później.Jeśli chcesz takie zachowanie dla wszystkich poleceń w skrypcie, po prostu dodaj
na początku skryptu. Ta para opcji informuje interpretera bash, aby zakończył działanie za każdym razem, gdy polecenie powróci z niezerowym kodem wyjścia.
Nie pozwala to jednak na wydrukowanie komunikatu wyjścia.
źródło
trap
wbudowanego polecenia bash.set -o pipefail
może nie być pożądanym zachowaniem. Wciąż dziękuję za zwrócenie na to uwagi!set -e
nie jest wcale wiarygodny, spójny ani przewidywalny! Aby się o tym przekonać, przejrzyj sekcję ćwiczeń BashFAQ # 105 lub tabelę porównującą zachowania różnych muszli na stronie inulm.de/~mascheck/various/set-eZhackowałem następujący idiom:
Poprzedź każde polecenie informacyjnym echem i podążaj za każdym poleceniem w tym samym
if [ $? -ne 0 ];...
wierszu. (Oczywiście możesz edytować ten komunikat o błędzie, jeśli chcesz).źródło
if ! javac *.java; then ...
- po$?
co w ogóle zawracać sobie głowę ?Pod warunkiem, że
my_command
jest kanonicznie zaprojektowany, tzn. Zwraca 0, gdy się powiedzie, to&&
jest dokładnie odwrotne niż chcesz. Chcesz||
.Zauważ też, że
(
nie wydaje mi się to właściwe w bash, ale nie mogę spróbować z miejsca, w którym jestem. Powiedz mi.źródło
Możesz także użyć, jeśli chcesz zachować status błędu wyjścia i mieć czytelny plik z jednym poleceniem w wierszu:
Nie spowoduje to jednak wydrukowania dodatkowego komunikatu o błędzie. Ale w niektórych przypadkach błąd i tak zostanie wydrukowany przez nieudane polecenie.
źródło
exit $?
; po prostuexit
używa$?
jako wartości domyślnej.trap
Wbudowane Powłoka umożliwia chwytnych sygnały oraz inne korzystne warunki, w tym nieudanej realizacji poleceń (tj niezerowym w obie strony). Więc jeśli nie chcesz jawnie testować statusu powrotu każdej pojedynczej komendy, którą możesz wypowiedzieć,trap "your shell code" ERR
a kod powłoki zostanie wykonany za każdym razem, gdy komenda zwróci niezerowy status. Na przykład:trap "echo script failed; exit 1" ERR
Zauważ, że podobnie jak w innych przypadkach chwytania nieudanych poleceń, rurociągi wymagają specjalnego traktowania; powyższe nie złapie
false | true
.źródło