Co oznacza set-e w skrypcie bash?

Badam zawartość pliku preinst, który skrypt wykonuje przed rozpakowaniem pakietu z jego archiwum Debiana (.deb) plik.

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 wyświetla komunikat "MyApplicationName is just installed" i kończy się (return 1 oznacza, że kończy się "błędem", 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ś przeoczyłem?
Author: klay, 2013-10-27

4 answers

From help set:

  -e  Exit immediately if a command exits with a non-zero status.

Ale to jest uważane za złą praktykę przez niektórych ludzi (Bash FAQ i takie jak ludzie piszący ten FAQ na IRC freenode #bash), lepiej używać:

trap 'do_something' ERR

Aby uruchomić funkcję do_something w przypadku wystąpienia błędów.

Zobacz http://mywiki.wooledge.org/BashFAQ/105

 491
Author: Gilles Quenot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-13 12:39:48

set -e zatrzymuje wykonywanie skryptu, jeśli polecenie lub potok ma błąd-który jest przeciwieństwem domyślnego zachowania powłoki, czyli ignorowania błędów w skryptach. Wpisz help set w Terminalu, aby zobaczyć dokumentację tego wbudowanego polecenia.

 61
Author: Robin Green,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-27 19:14:29

Zgodnie z bash-Zestaw Wbudowany manual, Jeśli -e/errexit jest ustawione, powłoka natychmiast wychodzi, jeśli rurociąg składa się z pojedynczego prostego polecenia, lista lub polecenie złożone zwraca niezerowy status.

Domyślnie, status zakończenia potoku jest statusem zakończenia ostatniego polecenia w potoku, chyba że opcja pipefail jest włączona (domyślnie jest wyłączona).

Jeśli tak, to status powrotu rurociągu ostatniego (prawe) polecenie wyjścia ze statusem 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:

trap onexit EXIT

Gdzie onexit jest twoją funkcją do zrobienia czegoś przy wyjściu, jak poniżej, która drukuje prosty ślad stosu :

onexit(){ while caller $((n++)); do :; done; }

Istnieje podobna opcja -E/errtrace co byłoby pułapką na ERR zamiast, np.:

trap onerr ERR

Przykłady

Status Zero przykład:

$ true; echo $?
0
Przykład stanu niezerowego:
$ false; echo $?
1

Przykłady negacji statusu:

$ ! false; echo $?
0
$ false || true; echo $?
0

Test z pipefail jest wyłączony:

$ bash -c 'set +o pipefail -e; true | true | true; echo success'; echo $?
success
0
$ bash -c 'set +o pipefail -e; false | false | true; echo success'; echo $?
success
0
$ bash -c 'set +o pipefail -e; true | true | false; echo success'; echo $?
1

Test z włączoną funkcją pipefail:

$ bash -c 'set -o pipefail -e; true | false | true; echo success'; echo $?
1
 34
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:11

Znalazłem to pytanie podczas googlowania, próbując dowiedzieć się, jaki był status zakończenia skryptu, który został przerwany z powodu set -e. Odpowiedź nie wydawała mi się oczywista, stąd ta odpowiedź. Zasadniczo, set -e przerywa wykonywanie polecenia (np. skryptu powłoki) i zwraca kod statusu zakończenia polecenia, które nie powiodło się (np. skrypt wewnętrzny, nie skrypt zewnętrzny).

Na przykład, załóżmy, że mam skrypt powłoki outer-test.sh:

#!/bin/sh
set -e
./inner-test.sh
exit 62;

Kod dla inner-test.sh jest:

#!/bin/sh
exit 26;

Kiedy uruchamiam outer-script.sh z linii poleceń mój skrypt zewnętrzny kończy się kodem wyjścia skryptu wewnętrznego:

$ ./outer-test.sh
$ echo $?
26
 32
Author: entpnerd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-13 18:18:48