Dla pewności chciałbym bash przerwać wykonywanie skryptu, jeśli napotka błąd składniowy.
Ku mojemu zaskoczeniu nie mogę tego osiągnąć. ( set -e
to za mało.) Przykład:
#!/bin/bash
# Do exit on any error:
set -e
readonly a=(1 2)
# A syntax error is here:
if (( "${a[#]}" == 2 )); then
echo ok
else
echo not ok
fi
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Wynik (bash-3.2.39 lub bash-3.2.51):
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 10: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Nie możemy sprawdzać $?
po każdej instrukcji, aby wyłapać błędy składniowe.
(Spodziewałem się takiego bezpiecznego zachowania z rozsądnego języka programowania ... być może należy to zgłosić jako błąd / chęć bashowania deweloperów)
Więcej eksperymentów
if
nie robi różnicy.
Usuwanie if
:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
(( "${a[#]}" == 2 ))
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Wynik:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
Być może jest to związane z ćwiczeniem 2 z http://mywiki.wooledge.org/BashFAQ/105 i ma coś wspólnego z tym (( ))
. Ale nadal uważam, że nadal nieuzasadnione jest kontynuowanie wykonywania po błędzie składni.
Nie, (( ))
nie ma znaczenia!
Zachowuje się źle nawet bez testu arytmetycznego! Po prostu prosty, podstawowy skrypt:
#!/bin/bash
set -e # exit on any error
readonly a=(1 2)
# A syntax error is here:
echo "${a[#]}"
echo status $?
echo 'Bad: has not aborted execution on syntax error!'
Wynik:
$ ./sh-on-syntax-err
./sh-on-syntax-err: line 6: #: syntax error: operand expected (error token is "#")
status 1
Bad: has not aborted execution on syntax error!
$
bash
shell-script
error-handling
imz - Ivan Zakharyaschev
źródło
źródło
set -e
nie wystarczy, ponieważ błąd składniowy znajduje się wif
instrukcji. Gdziekolwiek indziej powinien przerwać skrypt.set -e
nie zadziałało. Ale moje pytanie wciąż ma sens. Czy można przerwać dowolny błąd składniowy?Odpowiedzi:
Zawinięcie całości w funkcję wydaje się załatwić sprawę:
Wynik:
Chociaż nie mam pojęcia, dlaczego - może ktoś inny może to wyjaśnić?
źródło
echo 'Bad2: has not aborted the execution after bad main!'
jako ostatni do twojego przykładu, a wynik jest następujący: $ LC_ALL = C ./sh-on-syntax-err ./sh-on-syntax-err: linia 6: #: błąd składni: oczekiwany operand ( token błędu to „#”) Bad2: nie przerwał wykonywania po złym main! $Prawdopodobnie wprowadzasz w błąd co do prawdziwego znaczenia
set -e
. Uważne czytanie wynikówhelp set
programów:Podobnie
-e
jest z niezerowym statusem zakończenia poleceń , a nie z błędami składni w skrypcie.Ogólnie rzecz biorąc, uważa się za złą praktykę
set -e
, ponieważ wszystkie błędy (tj. Wszystkie niezerowe zwroty z poleceń) powinny być inteligentnie obsługiwane przez skrypt (pomyśl solidny skrypt, a nie te, które szaleją po wprowadzeniu nazwy pliku za pomocą spacja lub zaczynająca się od myślnika).W zależności od rodzaju błędu składniowego skrypt może nawet nie zostać w ogóle wykonany. Nie mam wystarczającej wiedzy na temat bash, aby powiedzieć dokładnie, jaką klasę błędów składniowych (jeśli tylko można je sklasyfikować) może prowadzić do natychmiastowej aborcji skryptu, czy nie. Może dołączy do nich jakiś guru Bash i wszystko wyjaśni.
Mam tylko nadzieję, że wyjaśniłem to
set -e
oświadczenie!O twoim życzeniu:
Odpowiedź jest zdecydowanie nie! ponieważ to, co zaobserwowałeś (
set -e
nie reagujesz tak, jak się spodziewałeś) jest w rzeczywistości bardzo dobrze udokumentowane.źródło
set -e
- jest to trochę blisko moich celów, dlatego jest tutaj wspomniane i wykorzystywane. Moje pytanie nie dotyczyset -e
, dotyczy bezpieczeństwa bashu, jeśli nie można go przerwać w przypadku błędów sytax. Szukam sposobu, aby zawsze przerywał błędy składniowe.Możesz sam sprawdzić skrypt, umieszczając coś takiego
u góry skryptu - po,
set -e
ale przed jakimkolwiek znaczącym fragmentem kodu.Muszę powiedzieć, że to nie wydaje się bardzo solidne, ale jeśli to działa dla ciebie, być może jest to do przyjęcia.
źródło
set -e
:bash -n "$0" || exit
Po pierwsze,
(( ))
bash jest używany jako obliczenia arytmetyczne, a nie do użycia w if ... użyj[]
do tego.Po drugie,
${a[#]}
jest dziwne i dlatego daje błędy ...#
nie ma żadnego znaczenia tablicowegoNie wiem, co chcesz z tym zrobić, ale zakładam, że chcesz znać liczbę pól, więc
${#a[*]}
zamiast tegoWreszcie, podczas porównywania liczb całkowitych,
-eq
zalecane jest nad==
(używane do łańcuchów).==
będzie również działać, ale-eq
jest zalecane.więc chcesz:
źródło
((
słowa kluczowego zeif
słowem kluczowym. Na przykładif (( 5 * $b > 53 ))
. O ile nie dążysz do przenośności ze starszymi pociskami,[[
jest to zwykle lepsze niż[
.[[
i((
zostały zaprojektowane specjalnie jako lekkie testy do użycia z „jeśli” itp. - w przeciwieństwie do tego[
, nigdy nie spawnują podprocesu do oceny stanu.[
jest wbudowanym bash. Starsze powłoki oczekują jednak, że będzie to własny program.