Come convalidare la sintassi di uno script Bash Linux prima di eseguirlo

0
14
Un terminale Linux sullo schermo del laptop su uno sfondo rosso.
fatmawati achmad zaenuri/Shutterstock

Bug e refusi negli script di Linux Bash possono fare cose terribili quando lo script viene eseguito. Ecco alcuni modi per controllare la sintassi dei tuoi script prima ancora di eseguirli.

Quei fastidiosi insetti

Scrivere codice è difficile. O per essere più precisi, scrivere codice non banale privo di bug è difficile. E più righe di codice ci sono in un programma o script, più è probabile che ci siano dei bug.

La lingua in cui si programma ha un’influenza diretta su questo. La programmazione in assembly è molto più difficile della programmazione in C e la programmazione in C è più impegnativa della programmazione in Python. Più basso è il linguaggio in cui stai programmando, più lavoro devi fare da solo. Python potrebbe godere di routine di garbage collection integrate, ma C e assembly certamente no.

Che cos

IMPARENTATOChe cos’è un “bug del computer” e da dove viene il termine?

La scrittura di script di shell Linux pone le proprie sfide. Con un linguaggio compilato come C, un programma chiamato compilatore legge il tuo codice sorgente, le istruzioni leggibili dall’uomo che digiti in un file di testo, e lo trasforma in un file eseguibile binario. Il file binario contiene le istruzioni del codice macchina che il computer può comprendere e utilizzare.

Il compilatore genererà un file binario solo se il codice sorgente che sta leggendo e analizzando obbedisce alla sintassi e ad altre regole del linguaggio. Se si scrive a parola riservata—una delle parole di comando della lingua—o un nome di variabile errato, il compilatore genererà un errore.

Come lavorare con le variabili in Bash

IMPARENTATOCome lavorare con le variabili in Bash

Ad esempio, alcune lingue insistono nel dichiarare una variabile prima di usarla, altre non sono così esigenti. Se la lingua in cui stai lavorando richiede di dichiarare variabili ma ti dimentichi di farlo, il compilatore genererà un messaggio di errore diverso. Per quanto fastidiosi siano questi errori di compilazione, catturano molti problemi e ti costringono ad affrontarli. Ma anche quando hai un programma che non ha bug sintattici non significa che non ci siano bug. Lontano da esso.

Annuncio

Bug che sono dovuti a difetti logici di solito sono molto più difficili da individuare. Se dici al tuo programma di aggiungere due più tre ma volevi davvero che aggiungesse due più due, non otterrai la risposta che ti aspettavi. Ma il programma sta facendo ciò per cui è stato scritto. Non c’è niente di sbagliato nella composizione o nella sintassi del programma. Il problema sei tu. Hai scritto un programma ben formato che non fa quello che volevi.

Il test è difficile

Testare a fondo un programma, anche semplice, richiede molto tempo. Eseguirlo un paio di volte non è sufficiente; hai davvero bisogno di testare tutti i percorsi di esecuzione nel tuo codice, in modo che tutte le parti del codice siano verificate. Se il programma richiede input, è necessario fornire un intervallo di valori di input sufficiente per testare tutte le condizioni, incluso input inaccettabile.

Per le lingue di livello superiore, i test unitari e i test automatizzati aiutano a rendere i test approfonditi un esercizio gestibile. Quindi la domanda è: ci sono strumenti che possiamo usare per aiutarci a scrivere script di shell Bash privi di bug?

La risposta è sì, inclusa la shell Bash stessa.

Utilizzo di Bash per controllare la sintassi dello script

Il Bash -n (noexec) l’opzione dice a Bash di leggere uno script e controllarlo per errori sintattici, senza eseguire lo script. A seconda di ciò che lo script è destinato a fare, questo può essere molto più sicuro che eseguirlo e cercare problemi.

Ecco lo script che andremo a controllare. Non è complicato, è principalmente un insieme di if dichiarazioni. Richiede e accetta un numero che rappresenta un mese. La sceneggiatura decide a quale stagione appartiene il mese. Ovviamente, questo non funzionerà se l’utente non fornisce alcun input o se fornisce input non validi come una lettera anziché una cifra.

#! /bin/bash

read -p "Enter a month (1 to 12): " month

# did they enter anything?
if [ -z "$month" ]
then
  echo "You must enter a number representing a month."
  exit 1
fi

# is it a valid month?
if (( "$month" < 1 || "$month" > 12)); then
  echo "The month must be a number between 1 and 12."
  exit 0
fi

# is it a Spring month?
if (( "$month" >= 3 && "$month" < 6)); then
  echo "That's a Spring month."
  exit 0
fi

# is it a Summer month?
if (( "$month" >= 6 && "$month" < 9)); then
  echo "That's a Summer month."
  exit 0
fi

# is it an Autumn month?
if (( "$month" >= 9 && "$month" < 12)); then
  echo "That's an Autumn month."
  exit 0
fi

# it must be a Winter month
echo "That's a Winter month."
exit 0
Annuncio

Questa sezione controlla se l’utente ha inserito qualcosa. Verifica se il $month la variabile non è impostata.

if [ -z "$month" ]
then
  echo "You must enter a number representing a month."
  exit 1
fi

Questa sezione controlla se hanno inserito un numero compreso tra 1 e 12. Intrappola anche l’input non valido che non è una cifra, perché lettere e segni di punteggiatura non si traducono in valori numerici.

# is it a valid month?
if (( "$month" < 1 || "$month" > 12)); then
  echo "The month must be a number between 1 and 12."
  exit 0
fi

Tutte le altre clausole If controllano se il valore in $month variabile è tra due valori. Se lo è, il mese appartiene a quella stagione. Ad esempio, se il mese inserito dall’utente è 6, 7 o 8, è un mese estivo.

# is it a Summer month?
if (( "$month" >= 6 && "$month" < 9)); then
  echo "That's a Summer month."
  exit 0
fi

Se vuoi elaborare i nostri esempi, copia e incolla il testo dello script in un editor e salvalo come “seasons.sh”. Quindi rendi eseguibile lo script usando il file chmod comando:

chmod +x seasons.sh

Impostazione dell'autorizzazione eseguibile su uno script

Possiamo testare lo script da

  • Non fornendo alcun input.
  • Fornire un input non numerico.
  • Fornire un valore numerico al di fuori dell’intervallo da 1 a 12.
  • Fornire valori numerici compresi tra 1 e 12.

In tutti i casi, avviamo lo script con lo stesso comando. L’unica differenza è l’input fornito dall’utente quando promosso dallo script.

./seasons.sh

Testare uno script con una varietà di input validi e non validi

Sembra funzionare come previsto. Facciamo controllare a Bash la sintassi del nostro script. Lo facciamo invocando il -n (noexec) e passando il nome del nostro script.

bash -n ./seasons.sh

Utilizzo di Bash per testare la sintassi di uno script

Annuncio

Questo è un caso di “nessuna notizia è una buona notizia”. Tornarci silenziosamente al prompt dei comandi è il modo in cui Bash dice che tutto sembra a posto. Sabotiamo il nostro script e introduciamo un errore.

Rimuoveremo il then dal primo if clausola.

# is it a valid month?
if (( "$month" < 1 || "$month" > 12)); # "then" has been removed
  echo "The month must be a number between 1 and 12."
  exit 0
fi

Ora eseguiamo lo script, prima senza e poi con l’input dell’utente.

./seasons.sh

Testare uno script con input non validi e validi

La prima volta che lo script viene eseguito, l’utente non inserisce un valore e quindi lo script viene terminato. La sezione che abbiamo sabotato non viene mai raggiunta. Lo script termina senza un messaggio di errore da Bash.

La seconda volta che lo script viene eseguito, l’utente fornisce un valore di input e la prima clausola if viene eseguita per verificare l’integrità dell’input dell’utente. Ciò attiva il messaggio di errore da Bash.

Nota che Bash controlla la sintassi di quella clausola, e di ogni altra riga di codice, perché non gli interessa logica della sceneggiatura. All’utente non viene richiesto di inserire un numero quando Bash controlla lo script, perché lo script non è in esecuzione.

I diversi possibili percorsi di esecuzione dello script non influenzano il modo in cui Bash controlla la sintassi. Bash si fa strada in modo semplice e metodico dall’inizio alla fine dello script, controllando la sintassi per ogni riga.

L’utilità ShellCheck

Un linter, che prende il nome da uno strumento di controllo del codice sorgente C dei tempi d’oro di Unix, è uno strumento di analisi del codice utilizzato per rilevare errori di programmazione, errori stilistici e uso sospetto o discutibile del linguaggio. I linter sono disponibili per molti linguaggi di programmazione e sono rinomati per essere pedanti. Non tutto ciò che trova un linter è un bug di per séma tutto ciò che portano alla tua attenzione probabilmente merita attenzione.

Annuncio

ShellCheck è uno strumento di analisi del codice per gli script di shell. Si comporta come un linter per Bash.

Mettiamo il nostro disperso then parola riservata nel nostro script e prova qualcos’altro. Rimuoveremo la parentesi di apertura “[”findall’inizio[”fromtheveryfirstif clausola.

# did they enter anything?
if -z "$month" ] # opening bracket "[" removed
then
  echo "You must enter a number representing a month."
  exit 1
fi

se usiamo Bash per controllare lo script non ci sono problemi.

bash -n seasons.sh
./seasons.sh

Un messaggio di errore da uno script che ha superato il controllo della sintassi senza che siano stati rilevati problemi

Ma quando ci proviamo correre lo script vediamo un messaggio di errore. E, nonostante il messaggio di errore, lo script continua a essere eseguito. Questo è il motivo per cui alcuni bug sono così pericolosi. Se le azioni intraprese più avanti nello script si basano sull’input valido dell’utente, il comportamento dello script sarà imprevedibile. Potrebbe potenzialmente mettere a rischio i dati.

Il motivo del Bash -n (noexec) l’opzione non trova l’errore nello script è la parentesi di apertura “[”èunprogrammaesternochiamato[”isanexternalprogramcalled[. Non fa parte di Bash. È un modo abbreviato di usare il test comando.

Annuncio

Bash non controlla l’uso di programmi esterni durante la convalida di uno script.

Installazione di ShellCheck

ShellCheck richiede l’installazione. Per installarlo su Ubuntu, digita:

sudo apt install shellcheck

Installazione di shellcheck su Ubuntu

Per installare ShellCheck su Fedora, usa questo comando. Nota che il nome del pacchetto è in maiuscolo misto, ma quando esegui il comando nella finestra del terminale è tutto in minuscolo.

sudo dnf install ShellCheck

Installazione di shellcheck su Fedora

Su Manjaro e distribuzioni simili basate su Arch, utilizziamo pacman:

sudo pacman -S shellcheck

Installazione di shellcheck su Manjaro

Utilizzando ShellCheck

Proviamo a eseguire ShellCheck sul nostro script.

shellcheck seasons.sh

Controllo di uno script con ShellCheck

ShellCheck rileva il problema, ce lo segnala e fornisce una serie di collegamenti per ulteriori informazioni. Se fai clic con il pulsante destro del mouse su un collegamento e scegli “Apri collegamento” dal menu contestuale visualizzato, il collegamento si aprirà nel tuo browser.

ShellCheck segnala errori e avvisi

ShellCheck trova anche un altro problema, che non è così grave. È riportato in testo verde. Ciò indica che si tratta di un avviso, non di un vero e proprio errore.

Correggiamo il nostro errore e sostituiamo il “[”mancanteUnastrategiadicorrezionedeibugconsistenelcorreggereprimaiproblemiconlaprioritàpiùaltaepoiridurreiproblemiconlaprioritàpiùbassacomegliavvisi[”Onebug-fixstrategyistocorrectthehighestpriorityissuesfirstandworkdowntothelowerpriorityissueslikewarningslater

Abbiamo sostituito il “[“mancanteedeseguitoancoraunavoltaShellCheck[”andranShellCheckoncemore

shellcheck seasons.sh

Controllo di uno script una seconda volta con ShellCheck

Annuncio

L’unico output di ShellCheck si riferisce al nostro avviso precedente, quindi va bene. Non abbiamo problemi ad alta priorità da risolvere.

L’avviso ci dice che usando il read comando senza il -r L’opzione (leggi così com’è) farà sì che le barre inverse nell’input vengano trattate come caratteri di escape. Questo è un buon esempio del tipo di output pedante che può generare un linter. Nel nostro caso l’utente non dovrebbe comunque inserire una barra rovesciata: abbiamo bisogno che inserisca un numero.

Avvisi come questo richiedono un giudizio da parte del programmatore. Fare lo sforzo di aggiustarlo o lasciarlo così com’è? È una semplice correzione di due secondi. E fermerà l’avviso che ingombra l’output di ShellCheck, quindi potremmo anche seguire il suo consiglio. Aggiungeremo una “r” per opzionare i flag su read comando e salvare lo script.

read -pr "Enter a month (1 to 12): " month

L’esecuzione di ShellCheck ancora una volta ci dà un buono stato di salute.

Nessun errore o avviso segnalato da ShellCheck

ShellCheck è tuo amico

ShellCheck è in grado di rilevare, segnalare e fornire consigli su un’intera gamma di problemi. Dai un’occhiata alla loro galleria di codice errato, che mostra quanti tipi di problemi può rilevare.

È gratuito, veloce e rimuove molto il dolore dalla scrittura di script di shell. Cosa non va?

LEAVE A REPLY

Please enter your comment!
Please enter your name here