Come posso verificare la sintassi di uno script Bash senza eseguirlo?


Risposte:


381
bash -n scriptname

Forse un ovvio avvertimento: questo convalida la sintassi ma non verificherà se il tuo script bash tenta di eseguire un comando che non è nel tuo percorso, come ech helloinvece di echo hello.


9
Nella manpage di bash, sotto "SHELL BUILTIN COMMANDS / set", -n è documentato e, come indicato all'inizio della manpage, bash interpreta tutte le opzioni a carattere singolo che lo setfanno.
effimero

24
da aggiungere all'avvertimento (per me) non ovvio, inoltre non rileva un errore causato da uno spazio mancante if ["$var" == "string" ]anzichéif [ "$var" == "string" ]
Brynjar

11
@Brynjar Questo perché è solo un controllo della sintassi. La parentesi aperta non è sintassi, questo è il nome della funzione da eseguire. type [dice "[è una shell integrata". Alla fine delega al testprogramma, ma si aspetta anche una parentesi di chiusura. Quindi è come if test"$var", non è quello che intendeva l'autore, ma è sintatticamente valido (diciamo che $ var ha un valore di "a", quindi vedremo "bash: testa: comando non trovato"). Il punto è che sintatticamente, non c'è spazio mancante.
Joshua Cheek,

2
@JoshuaCheek: [in questo caso il comando incorporato viene invocato solo se si $varverifica l'espansione in una stringa vuota . Se si $varespande in una stringa non vuota , [viene concatenato con quella stringa e viene interpretato come un nome di comando (non il nome della funzione ) da Bash e, sì, che è sintatticamente valido, ma, come dici tu, ovviamente non è l'intento. Se si utilizza [[invece di [, anche se [[è una parola chiave shell (piuttosto che un built-in), si otterrà lo stesso risultato, poiché la concatenazione di stringhe non intenzionali ignora ancora il riconoscimento della parola chiave.
mklement0

2
@JoshuaCheek: Bash sta ancora sintatticamente -controllando qui: sta controllando la sintassi di invocazione a comando semplice : sintatticamente["$var" è un'espressione nome-comando valida ; allo stesso modo, i token e sono validi argomenti di comando . (In generale, incorporato viene analizzato con comando sintassi, mentre - come un guscio parola - viene analizzato in modo diverso.) Il comando incorporato shell non non delegare al " programma" (utilità esterna): , , , tutti hanno incorporato versioni sia e=="$string"[[[[ testbashdashkshzsh[teste non chiamano le loro controparti di utilità esterna.
mklement0,

127

Il tempo cambia tutto. Ecco un sito Web che fornisce il controllo della sintassi online per lo script della shell.

Ho scoperto che è molto potente rilevare errori comuni.

inserisci qui la descrizione dell'immagine

Informazioni su ShellCheck

ShellCheck è uno strumento statico di analisi e sfilacciatura di script sh / bash. Si concentra principalmente sulla gestione di errori e insidie ​​tipiche della sintassi per principianti e di livello intermedio in cui la shell fornisce solo un messaggio di errore criptico o un comportamento strano, ma riporta anche alcuni problemi più avanzati in cui casi d'angolo possono causare guasti ritardati.

Il codice sorgente di Haskell è disponibile su GitHub!


5
Ottimo consiglio; su OSX è ora possibile installare anche la CLI shellcheck.net, shellcheck, via Homebrew : brew install shellcheck.
mklement0

3
Anche su Debian & Friends:apt-get install shellcheck
quell'altro ragazzo il

Per Ubuntu fidato questo pacchetto deve essere installato da trusty-backports.
Peterino,

Come accennato in precedenza, era necessaria una dipendenza affidabile e può installarlo come di seguito in Ubuntu 14.04: sudo apt-get -f install, quindi: sudo sudo apt-get install shellcheck
zhihong

Questo è davvero utile, ma non usa il parser di Bash ma il suo. Nella maggior parte dei casi questo è abbastanza buono e può identificare sia l'analisi che altri problemi, ma c'è almeno un caso limite (e probabilmente altri che non ho visto) in cui non analizza allo stesso modo.
Daniel H,

38

Abilito anche l'opzione 'u' su ogni script bash che scrivo per fare qualche controllo extra:

set -u 

Questo riporterà l'utilizzo di variabili non inizializzate, come nel seguente script 'check_init.sh'

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

Esecuzione dello script:

$ check_init.sh

Riporterà quanto segue:

./check_init.sh[4]: mesage: parametro non impostato.

Molto utile per catturare errori di battitura


4
ho impostato queste bandiere sempre nei miei script bash, se le supera, è bene andare "set -o errexit" "set -o nounset" "set -o pipefail"
μολὼν.λαβέ

+1 per set -usebbene questo non risponda realmente alla domanda, perché è necessario eseguire lo script per ottenere il messaggio di errore. Nemmeno bash -n check_init.shmostra
quell'avvertimento

23
sh  -n   script-name 

Esegui questo. Se ci sono errori di sintassi nello script, restituisce lo stesso messaggio di errore. Se non ci sono errori, viene fuori senza dare alcun messaggio. Puoi controllare immediatamente usando echo $?, che restituirà la 0conferma avvenuta senza errori.

Ha funzionato bene per me. Ho funzionato su un sistema operativo Linux, Bash Shell.


1
Sebbene non sia esattamente correlato al controllo della sintassi di bash - è abbastanza utile usare set -x e set + x per il debug dell'intero script o delle sezioni dello script
GuruM

Grazie per questo non sapevo non sapevo di -n ma quello che volevo era @GuruM> sh -x test.sh in quanto mostra l'output generato dello script
zzapper

1
Sì. Ho dimenticato di dire che alla riga di comando è possibile eseguire le seguenti operazioni: 1) bash -x test.sh #questo esegue l'intero script in "modalità debug" 2) set + x; bash test.sh; set -x #set modalità debug on / off prima / dopo l'esecuzione dello script Nello script: a) #! / bin / bash -x #add 'modalità debug' all'inizio dello script b) set + x; codice; imposta -x #add 'modalità debug' per qualsiasi sezione dello script
GuruM

sh -nprobabilmente non verificherà che lo script sia script Bash valido. Potrebbe dare falsi negativi. shè una variante della shell Bourne che di solito non è Bash. Ad esempio in Ubuntu Linux realpath -e $(command -v sh)dà / bin / dash
jarno il

4

Veramente controllo tutti gli script bash nella directory corrente per errori di sintassi SENZA eseguirli usando lo findstrumento:

Esempio:

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

Se vuoi usarlo per un singolo file, modifica il carattere jolly con il nome del file.


3

comando null [due punti] utile anche durante il debug per vedere il valore della variabile

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

utilizza espansioni di parametri
mug896

funziona, perché set -xmostra ogni riga prima che venga eseguita
rubo77


1

Se hai bisogno in una variabile della validità di tutti i file in una directory (git pre-commit hook, build lint script), puoi catturare l'output stderr dei comandi "sh -n" o "bash -n" (vedi altri risposte) in una variabile e hanno un "if / else" basato su quello

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

Cambia "sh" con "bash" a seconda delle tue esigenze

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.