Przerywanie skryptu powłoki, jeśli jakieś polecenie zwraca niezerową wartość?
Mam skrypt powłoki Bash, który wywołuje wiele poleceń. Chciałbym, aby skrypt powłoki automatycznie zakończył działanie z wartością zwracaną 1, jeśli któreś z poleceń zwróci wartość niezerową.
Czy jest to możliwe bez jawnego sprawdzania wyniku każdego polecenia?
Np.
dosomething1
if [[ $? -ne 0 ]]; then
exit 1
fi
dosomething2
if [[ $? -ne 0 ]]; then
exit 1
fi
9 answers
Dodaj to do początku skryptu:
set -e
Spowoduje to natychmiastowe wyjście powłoki, jeśli proste polecenie zakończy działanie z niezerową wartością końcową. Proste polecenie to dowolne polecenie nie będące częścią if, while, lub until test, lub częścią listy & & lub||.
Zobacz stronę podręcznika bash(1) na wewnętrznej komendzie "set", aby uzyskać więcej szczegółów.
Osobiście uruchamiam prawie wszystkie skrypty powłoki z "set-e". To naprawdę irytujące mieć skrypt uparcie kontynuować, gdy coś w środku zawodzi i łamie założenia do reszty scenariusza.
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
2016-11-21 11:18:12
Aby dodać do zaakceptowanej odpowiedzi:
Pamiętaj, że set -e
czasami to za mało, szczególnie jeśli masz rury.
Na przykład, załóżmy, że masz ten skrypt
#!/bin/bash
set -e
./configure > configure.log
make
... co działa zgodnie z oczekiwaniami: błąd w configure
przerywa wykonanie.
Jutro dokonasz pozornie błahej zmiany:
#!/bin/bash
set -e
./configure | tee configure.log
make
... a teraz to nie działa. Jest to wyjaśnione tutaj , a obejście (tylko Bash) jest dostępne:
#!/bin/bash set -e set -o pipefail ./configure | tee configure.log make
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-11-22 18:57:06
Instrukcje if w twoim przykładzie są niepotrzebne. Po prostu zrób to tak:
dosomething1 || exit 1
Jeśli skorzystasz z porad Ville Laurikari i użyjesz set -e
to dla niektórych poleceń może być konieczne użycie tego:
dosomething || true
|| true
spowoduje, że potok poleceń będzie miał zwracaną wartość true
, nawet jeśli polecenie się nie powiedzie, więc opcja -e
nie zabije skryptu.
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
2009-05-04 19:03:39
Jeśli masz czyszczenie, które musisz wykonać przy wyjściu, możesz również użyć 'trap' z pseudo-sygnałem ERR. Działa to tak samo jak zalewkowanie INT lub dowolnego innego sygnału; bash rzuca błąd, jeśli jakiekolwiek polecenie zakończy działanie z wartością niezerową:
# Create the trap with
# trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Partially turn off the trap.
trap - ERR
# Now a control-C will still cause cleanup, but
# a nonzero exit code won't:
ps aux | grep blahblahblah
Lub, szczególnie jeśli używasz "set-e", możesz zamknąć pułapkę; pułapka zostanie wykonana, gdy skrypt zakończy się z jakiegokolwiek powodu, włączając normalny koniec, przerwania, wyjście spowodowane opcją-e, itp.
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
2009-05-07 20:58:11
Uruchom go z -e
LUB set -e
na górze.
Zobacz też set -u
.
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-06-04 13:48:37
Zmienna $?
jest rzadko potrzebna. Pseudo-idiom command; if [ $? -eq 0 ]; then X; fi
powinien być zawsze zapisywany jako if command; then X; fi
.
Przypadki, w których $?
jest wymagane, są wtedy, gdy trzeba je sprawdzić pod wieloma wartościami:
command
case $? in
(0) X;;
(1) Y;;
(2) Z;;
esac
Lub gdy$?
wymaga ponownego użycia lub innego manipulowania:
if command; then
echo "command successful" >&2
else
ret=$?
echo "command failed with exit code $ret" >&2
exit $ret
fi
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
2009-12-16 10:18:54
Wyrażenie podobne do
dosomething1 && dosomething2 && dosomething3
Zatrzyma przetwarzanie, gdy jedno z poleceń powróci z niezerową wartością. Na przykład, następujące polecenie nigdy nie wyświetli "Gotowe":
cat nosuchfile && echo "done"
echo $?
1
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
2009-05-04 19:01:33
#!/bin/bash -e
Powinno wystarczyć.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-07-24 13:14:14
Po prostu wrzuciłem jeszcze jeden dla odniesienia, ponieważ było dodatkowe pytanie do Mark Edgars input i tutaj jest dodatkowy przykład i dotyka tematu ogólnie:
[[ `cmd` ]] && echo success_else_silence
Czyli to samo co cmd || exit errcode
Jak ktoś pokazał.
Np. Chcę się upewnić, że partycja jest odmontowana, jeśli jest zamontowana:
[[ `mount | grep /dev/sda1` ]] && umount /dev/sda1
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
2012-09-16 11:00:47