Aus Sicherheitsgründen möchte ich, dass Bash die Ausführung eines Skripts abbricht, wenn es auf einen Syntaxfehler stößt.
Zu meiner Überraschung kann ich das nicht erreichen. ( set -e
ist nicht genug.) Beispiel:
#!/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!'
Ergebnis (bash-3.2.39 oder 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!
$
Nun, wir können nicht $?
nach jeder Anweisung prüfen, ob Syntaxfehler vorliegen.
(Ich habe ein solches sicheres Verhalten von einer vernünftigen Programmiersprache erwartet ... vielleicht muss dies als Fehler gemeldet werden / möchte Entwickler verprügeln)
Weitere Experimente
if
macht keinen Unterschied.
Entfernen 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!'
Ergebnis:
$ ./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!
$
Vielleicht hat es etwas mit Übung 2 von http://mywiki.wooledge.org/BashFAQ/105 zu tun (( ))
. Aber ich finde es immer noch unvernünftig, die Ausführung nach einem Syntaxfehler fortzusetzen.
Nein, (( ))
macht keinen Unterschied!
Es verhält sich auch ohne den Rechentest schlecht! Nur ein einfaches, einfaches Skript:
#!/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!'
Ergebnis:
$ ./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!
$
quelle
set -e
ist nicht genug, weil Ihr Syntaxfehler in einerif
Anweisung ist. An jeder anderen Stelle sollte das Skript abgebrochen werden.set -e
es nicht funktioniert hat. Aber meine Frage macht immer noch Sinn. Ist es möglich, bei einem Syntaxfehler abzubrechen?Antworten:
Das Ganze in eine Funktion zu packen, scheint den Trick zu tun:
Ergebnis:
Obwohl ich keine Ahnung habe, warum - vielleicht kann jemand anderes erklären?
quelle
echo 'Bad2: has not aborted the execution after bad main!'
als letztes an Ihr Beispiel angehängt und die Ausgabe lautet: $ LC_ALL = C ./sh-on-syntax-err ./sh-on-syntax-err: Zeile 6: #: Syntaxfehler: Operand erwartet ( Fehlertoken ist "#") Bad2: hat die Ausführung nach Bad Main nicht abgebrochen! $Sie sind wahrscheinlich über die wahre Bedeutung von irregeführt
set -e
. Eine sorgfältige Lektüre der Ausgabe vonhelp set
Shows:Es geht also
-e
um den Beendigungsstatus von Befehlen ungleich Null, nicht um Syntaxfehler in Ihrem Skript.Im Allgemeinen wird die Verwendung als schlechte Praxis angesehen
set -e
, da alle Fehler (dh alle Rückgaben ungleich Null von Befehlen) vom Skript intelligent behandelt werden sollten (denken Sie an ein robustes Skript, nicht an diejenigen, die nach der Eingabe eines Dateinamens mit einem "wild" werden) Leerzeichen oder das beginnt mit einem Bindestrich).Je nach Art des Syntaxfehlers wird das Skript möglicherweise überhaupt nicht ausgeführt. Ich kenne mich in Bash nicht gut genug aus, um genau zu sagen , welche Art von Syntaxfehlern (wenn sie nur klassifiziert werden können) zu einem sofortigen Abbruch des Skripts führen könnten oder nicht. Vielleicht machen einige Bash-Gurus mit und klären alles.
Ich hoffe nur, dass ich die
set -e
Aussage geklärt habe !Über Ihren Wunsch:
Die Antwort ist definitiv nein! Das, was Sie beobachtet haben (
set -e
keine erwartungsgemäße Antwort), ist in der Tat sehr gut dokumentiert.quelle
set -e
- es ist nur ein bisschen nah an meinen Zielen, deshalb wird es hier erwähnt und verwendet. Bei meiner Frage geht es nicht umset -e
, es geht um die Unsicherheit von Bash, wenn es nicht möglich ist, bei Systemsteuerfehlern abzubrechen. Ich suche nach einer Möglichkeit, es bei Syntaxfehlern immer abbrechen zu lassen.Sie könnten das Skript dazu bringen, sich selbst zu überprüfen, indem Sie etwas wie setzen
Nahe dem oberen Rand des Skripts - nach,
set -e
aber vor einem signifikanten Teil des Codes.Ich muss sagen, das fühlt sich nicht sehr robust an, aber wenn es für Sie funktioniert, ist es vielleicht akzeptabel.
quelle
set -e
:bash -n "$0" || exit
Zuerst die
(( ))
In-Bash als arithmetische Berechnung verwendet, nicht für die If-Verwendung[]
.Zweitens die
${a[#]}
seltsam und deshalb werden Fehler ausgegeben ... das#
hat keine Array-BedeutungIch weiß nicht, was Sie damit machen wollen, aber ich gehe davon aus, dass Sie die Anzahl der Felder wissen wollen, also wollen Sie
${#a[*]}
stattdessenBeim Vergleichen von Ganzzahlen wird schließlich die Über-
-eq
Option empfohlen==
(wird für Zeichenfolgen verwendet). das==
wird auch funktionieren, wird aber-eq
empfohlen.also du möchtest:
quelle
((
Schlüsselwort mit demif
Schlüsselwort zu verwenden. Zum Beispielif (( 5 * $b > 53 ))
. Es sei denn , Sie sind mit dem Ziel für die Portabilität mit älteren Muscheln,[[
ist im allgemeinen bevorzugt über[
.[[
und((
wurde speziell als Lightweight-Test entwickelt, um mit "if" usw. verwendet[
zu werden.[
ist ein bash builtin. Ältere Shells erwarten jedoch, dass es sich um ein eigenes Programm handelt.