Wie überprüfe ich die Syntax eines Bash-Skripts, ohne es auszuführen?


Antworten:


380
bash -n scriptname

Vielleicht eine offensichtliche Einschränkung: Dies bestätigt Syntax aber nicht überprüfen , ob Ihr Bash - Skript versucht , einen Befehl auszuführen , die nicht in Ihrem Pfad ist, wie ech hellostatt echo hello.


9
In der Manpage von bash wird unter "SHELL BUILTIN COMMANDS / set" -n dokumentiert, und wie zu Beginn der Manpage angegeben, interpretiert bash alle einstelligen Optionen, die setdies tun .
Ephemient

24
Um die (für mich) nicht offensichtliche Einschränkung zu ergänzen, wird es auch keinen Fehler abfangen, der durch ein fehlendes Leerzeichen verursacht wird, if ["$var" == "string" ]anstattif [ "$var" == "string" ]
Brynjar

11
@Brynjar Das liegt daran, dass es sich nur um eine Syntaxprüfung handelt. Die offene Klammer ist keine Syntax, sondern der Name der auszuführenden Funktion. type [sagt "[ist eine eingebaute Shell". Es delegiert letztendlich an das testProgramm, erwartet aber auch eine schließende Klammer. Es ist also so, wie if test"$var"es der Autor nicht gemeint hat, aber syntaktisch gültig ist (sagen wir, $ var hat den Wert "a", dann sehen wir "bash: testa: Befehl nicht gefunden"). Punkt ist, dass syntaktisch kein Platz fehlt.
Joshua Cheek

2
@JoshuaCheek: Builtin [wird in diesem Fall nur aufgerufen, wenn $vares zu einer leeren Zeichenfolge erweitert wird . Wenn es $varzu einer nicht leeren Zeichenfolge erweitert wird, [wird es mit dieser Zeichenfolge verkettet und von Bash als Befehlsname (nicht Funktionsname ) interpretiert. Ja, das ist syntaktisch gültig, aber, wie Sie sagen, offensichtlich nicht die Absicht. Wenn Sie [[anstelle von verwenden [, obwohl [[es sich um ein Shell- Schlüsselwort handelt (und nicht um ein integriertes Schlüsselwort), erhalten Sie dasselbe Ergebnis, da die unbeabsichtigte Verkettung von Zeichenfolgen die Erkennung des Schlüsselworts weiterhin überschreibt.
mklement0

2
@JoshuaCheek: Bash prüft hier immer noch die Syntax : Es überprüft die Aufrufsyntax für einfache Befehle : ["$var"ist syntaktisch ein gültiger Befehlsnamenausdruck ; in ähnlicher Weise, Tokens ==und "$string"gelten Befehl Argumente . ( Im Allgemeinen builtin [mit geparst Befehlssyntax, während [[- als Schalen Schlüsselwort - anders analysiert wird.) Die Schale builtin [ist nicht übertragen auf das „ testProgramm“ (externe Dienstprogramm): bash, dash, ksh, zshhaben alle eingebauten Versionen der beiden [undtestUnd sie nicht nennen ihre Außen-Utility - Pendants.
mklement0

127

Zeit verändert alles. Hier ist eine Website, die eine Online-Syntaxprüfung für Shell-Skripte bietet.

Ich fand es sehr leistungsfähig, häufige Fehler zu erkennen.

Geben Sie hier die Bildbeschreibung ein

Über ShellCheck

ShellCheck ist ein statisches Analyse- und Flusenwerkzeug für Sh / Bash-Skripte. Es konzentriert sich hauptsächlich auf die Behandlung typischer Syntaxfehler und Fallstricke für Anfänger und Fortgeschrittene, bei denen die Shell nur eine kryptische Fehlermeldung oder ein seltsames Verhalten ausgibt, berichtet jedoch auch über einige fortgeschrittenere Probleme, bei denen Eckfälle zu verzögerten Fehlern führen können.

Haskell-Quellcode ist auf GitHub verfügbar!


5
Toller Tipp; Unter OSX können Sie jetzt auch die Shellcheck.net-CLI shellchecküber Homebrew installieren : brew install shellcheck.
mklement0

3
Auch auf Debian & Freunde:apt-get install shellcheck
dieser andere Typ

Für Ubuntu Trusty muss dieses Paket von installiert werden trusty-backports.
Peterino

Wie oben erwähnt, ist eine vertrauenswürdige Abhängigkeit erforderlich, die wie folgt in Ubuntu 14.04 installiert werden kann: sudo apt-get -f install, dann: sudo sudo apt-get install shellcheck
zhihong

Dies ist sehr nützlich, verwendet jedoch nicht den Parser von Bash, sondern einen eigenen. In den meisten Fällen ist dies gut genug und kann sowohl das Parsen als auch andere Probleme identifizieren, aber es gibt mindestens einen Randfall (und wahrscheinlich andere, den ich nicht gesehen habe), bei dem das Parsen nicht ganz auf die gleiche Weise erfolgt.
Daniel H

38

Ich aktiviere auch die Option 'u' für jedes Bash-Skript, das ich schreibe, um zusätzliche Überprüfungen durchzuführen:

set -u 

Dadurch wird die Verwendung nicht initialisierter Variablen gemeldet, wie im folgenden Skript 'check_init.sh'.

#!/bin/sh
set -u
message=hello
echo $mesage

Ausführen des Skripts:

$ check_init.sh

Wird folgendes melden:

./check_init.sh[4]: mesage: Parameter nicht gesetzt.

Sehr nützlich, um Tippfehler zu fangen


4
Ich setze diese Flags immer in meinen Bash-Skripten. Wenn sie diese bestehen, ist es gut, "set -o errexit" "set -o nounset" "set -o pipefail" zu setzen
μολὼν.λαβέ

+1, set -uobwohl dies die Frage nicht wirklich beantwortet, da Sie das Skript ausführen müssen, um die Fehlermeldung zu erhalten. Nicht einmal bash -n check_init.shzeigt diese Warnung
rubo77

23
sh  -n   script-name 

Führen Sie dies aus. Wenn das Skript Syntaxfehler enthält, wird dieselbe Fehlermeldung zurückgegeben. Wenn es keine Fehler gibt, wird es ohne Meldung ausgegeben. Sie können dies sofort überprüfen, indem Sie echo $?die 0Bestätigung ohne Fehler als erfolgreich zurückgeben.

Es hat bei mir gut funktioniert. Ich lief unter Linux OS, Bash Shell.


1
Obwohl dies nicht genau mit der Überprüfung der Bash-Syntax zusammenhängt - die Verwendung von set -x und set + x zum Debuggen des vollständigen Skripts oder von Abschnitten des Skripts ist sehr nützlich
GuruM

Danke, dass ich nicht wusste, dass ich nichts über das -n wusste, aber ich wollte @GuruM> sh -x test.sh, da dies die generierte Ausgabe des Skripts
anzeigt

1
Ja. Ich habe vergessen zu erwähnen, dass Sie in der Befehlszeile Folgendes tun können: 1) bash -x test.sh #dies führt das gesamte Skript im 'Debug-Modus' aus. 2) set + x; bash test.sh; setze -x # setze den Debug-Modus vor / nach dem Ausführen des Skripts ein / aus Im Skript: a) #! / bin / bash -x #add 'Debug-Modus' oben im Skript b) setze + x; Code; setze -x #add 'Debug-Modus' für jeden Abschnitt des Skripts
GuruM

sh -nwird wahrscheinlich nicht überprüfen, ob das Skript ein gültiges Bash-Skript ist. Es könnte falsche Negative geben. shist eine Bourne-Shell-Variante, die normalerweise nicht Bash ist. Zum Beispiel in Ubuntu Linux realpath -e $(command -v sh)gibt / bin / dash
jarno

4

Ich überprüfe tatsächlich alle Bash-Skripte im aktuellen Verzeichnis auf Syntaxfehler, OHNE sie mit dem findTool auszuführen :

Beispiel:

find . -name '*.sh' -exec bash -n {} \;

Wenn Sie es für eine einzelne Datei verwenden möchten, bearbeiten Sie einfach den Platzhalter mit dem Namen der Datei.


3

Der Befehl null [Doppelpunkt] ist auch beim Debuggen nützlich, um den Wert der Variablen anzuzeigen

set -x
for i in {1..10}; do
    let i=i+1
    : i=$i
done
set - 

es verwendet Parametererweiterungen
mug896

Dies funktioniert, weil set -xjede Zeile
angezeigt


1

Wenn Sie in einer Variablen die Gültigkeit aller Dateien in einem Verzeichnis benötigen (Git Pre-Commit-Hook, Build-Lint-Skript), können Sie die stderr-Ausgabe der Befehle "sh-n" oder "bash -n" abrufen (siehe andere) Antworten) in einer Variablen und haben ein "if / else" basierend darauf

bashErrLines=$(find bin/ -type f -name '*.sh' -exec sh -n {} \;  2>&1 > /dev/null)
  if [ "$bashErrLines" != "" ]; then 
   # at least one sh file in the bin dir has a syntax error
   echo $bashErrLines; 
   exit; 
  fi

Ändern Sie "sh" mit "bash", je nach Ihren Anforderungen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.