Bash Error Handling #3: logging, validazione input e test degli script

Immagine di copertina

Hai set -euo pipefail. Hai trap. Ti senti pronto/a.

Poi lo script fallisce in CI con l’iconico messaggio: Error: something went wrong.

Perfetto: hai scoperto che gestire gli errori non basta, bisogna anche spiegarli.

Logging utile: racconta cosa sta succedendo

Una funzione di log minima ma già utile:

log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
}

Questa funzione è di per sé minimale, ma super efficace: scrive su stderr con timestamp, permettendo di distinguere facilmente output dati e diagnostica. Prende un argomento variabile, così che si possa loggare qualsiasi messaggio.

Vediamone un utilizzo concreto:

log "Avvio deploy"
docker build -t myapp:latest .
log "Push immagine"
docker push myapp:latest
log "Deploy completato"

In questo modo, avremo un output chiaro e leggibile, con messaggi di log che indicano chiaramente le fasi del processo, come mostrato nell’esempio sopra.

Potresti chiederti, perché su stderr?

  • stdout resta libero per output dati, che potrebbero essere catturati da altri comandi o script
  • stderr contiene diagnostica: – quando fai debug, ringrazi te stesso – quando fai pipe, ringrazi te stesso

Validazione input: non fidarti (neanche di te)

Vediamo in questo esempio uno script fragile:

#!/usr/bin/env bash
set -euo pipefail

TARGET_ENV=${1}
./deploy.sh "$TARGET_ENV"

Cosa può andare storto? Se manca il parametro, TARGET_ENV sarà vuoto e il deploy fallirà in modo poco chiaro. Se qualcuno scrive ./deploy-wrapper.sh prodt, il deploy andrà su un ambiente inventato.

Meglio esplicitarlo e validare l’input:

#!/usr/bin/env bash
set -euo pipefail

TARGET_ENV=${1:-}

if [[ -z "$TARGET_ENV" ]]; then
  echo "Uso: $0 <dev|staging|prod>" >&2
  exit 1
fi

case "$TARGET_ENV" in
  dev|staging|prod) ;;
  *)
    echo "Ambiente non valido: $TARGET_ENV" >&2
    exit 1
    ;;
esac

L’istruzione case permette di definire chiaramente quali ambienti sono validi, e fornisce un messaggio di errore chiaro se l’input non è accettabile. Un po’ come avviene con switch in Java o C#, ma con la leggerezza di Bash.

Virgolette a profusione

Non è un vezzo stilistico. È sopravvivenza.

  • usa "$var", non $var
  • usa [[ ... ]] invece di [ ... ] quando possibile
  • evita eval salvo casi ultra controllati

Una variabile non quotata oggi è un bug intermittente domani. Questo perché le virgolette prevengono l’espansione indesiderata di spazi, caratteri speciali e globbing, che possono portare a comportamenti imprevedibili.

Nel dubbio, quotare è la scelta più sicura.

Testare Bash: sì, si può

Lo sappiamo, i test sono il neo di tutto lo sviluppo software, ancor più in Bash. Ma non è vero che non si possa fare.

Con Bats puoi verificare comportamento e codici di uscita.

@test "fallisce senza argomento" {
  run ./deploy-wrapper.sh
  [ "$status" -eq 1 ]
  [[ "$output" == *"Uso:"* ]]
}

Non serve testare tutto al millimetro il primo giorno, ma basta iniziare dai casi che in passato ti hanno fatto perdere più tempo. Path relativi che non esistono? Parametri obbligatori dimenticati? Comandi che falliscono in modo silenzioso? Questi sono ottimi candidati per i primi test.

Quando Bash non è la scelta giusta

Se lo script cresce troppo (parsing complesso, strutture dati, logica articolata), valuta di usare Python o Go.

Bash è un ottimo alleato per orchestrare comandi e automatizzare task, ma non è pensato per essere un framework applicativo completo. Se ti ritrovi a scrivere centinaia di righe di Bash per gestire logica complessa, probabilmente stai forzando lo strumento oltre le sue capacità naturali.

Bash è bravissimo a orchestrare comandi. Bash è pessimo quando diventa un framework applicativo travestito da script.

Nessuno ti premierà per aver scritto 600 righe di Bash, che potevano essere 80 righe chiare altrove, anzi.

In sintesi

Un buon script Bash non è quello che “funziona sul mio laptop”; è quello che:

  • fallisce quando deve fallire
  • pulisce quando deve pulire
  • spiega cosa sta facendo
  • valida gli input
  • e testabile

Con questo chiudiamo la mini-serie: meno fatalismo, più automazione affidabile e consapevolezza. Non è magia, è disciplina.

Conosci meglio chi ha scritto questo articolo

Serena Sensini

Ciao! Mi chiamo Serena Sensini e sono la creatrice di @ TheRedCode.it. Ho aperto questo blog nel 2021 per raccontare il mio lavoro e il mondo dell’informatica a parole semplici, in piccole pillole e alla portata di tutte le persone.

Sono un’ingegnera informatica specializzata in ambito AI & NLP. Di giorno lavoro come CTO @ Welyk e come Innovation & Emerging Technologies Leader @ Dedalus, mentre di notte scrivo e sono autrice di 5 libri -per ora-. 🖊️

Foto di Serena Sensini

Partners

Community, aziende e persone che supportano attivamente il blog

Vuoi diventare partner?

Collaboriamo con community, aziende e strumenti del mondo tech che vogliono raggiungere la nostra community di dev ed engineer italiani. Scrivici per proporre una collaborazione.

Vuoi diventare tech content creator? 🖊️

Se ti va di raccontare la tua esperienza nel mondo tech, questo è il posto giusto.

Cerchiamo voci autentiche, esempi pratici e punti di vista utili per chi legge.

Scrivici a collaborazioni[at]theredcode.it con una proposta: idea, taglio del contenuto e una breve presentazione. Non vediamo l'ora di leggere la tua esperienza!

Invia la tua idea