Si chiamano comunemente codici di uscita (in inglese exit codes o exit status). Sono un concetto fondamentale nei sistemi operativi Unix-like (Linux, macOS, BSD, ecc.) e vengono utilizzati per comunicare l’esito dell’esecuzione di un programma o comando.
Un codice di uscita è un valore intero che un processo restituisce al proprio processo padre (tipicamente la shell da cui è stato lanciato) nel momento in cui la sua esecuzione termina. Questo valore fornisce informazioni sull’esito dell’esecuzione; quindi se il comando è stato completato con successo oppure ha generato un errore.
Principio fondamentale:
0
(zero): indica il successo. Il programma si è concluso correttamente e senza errori.- Qualsiasi valore diverso da
0
: segnala un errore o un fallimento. Il significato preciso può variare a seconda del programma.
I codici di uscita sono fondamentali per la scrittura di script shell e per l’automazione, in quanto consentono di verificare il risultato dei comandi e prendere decisioni di conseguenza.
Verifica del codice di uscita ($?
)
In Bash (e shell simili), il codice di uscita dell’ultimo comando eseguito è memorizzato nella variabile speciale $?
. Per esempio:
ls /tmp/file_esistente.txt
echo $? # Output: 0
ls /tmp/file_non_esistente.txt
echo $? # Output: 2 (file o directory non trovati)
Bash – Usare gli operatori di controllo (&&
e ||
) per direzionare le esecuzioni di più comandi
&& e ||:
questi due operatori logici condizionali sfruttano i codici di uscita per decidere se eseguire il comando successivo. Quindi:
comando1 && comando2
: eseguecomando2
solo secomando1
termina con successo (cioè con codice 0).mkdir mia_dir && cd mia_dir && echo "Directory creata e navigata."
comando1 || comando2
: eseguecomando2
solo secomando1
termina con un errore (cioè con codice diverso da 0).grep "parola" file_inesistente.txt || echo "File inesistente o parola non trovata."
Script Bash – sfruttare l’exit code per rendere più dinamico l’output
Negli script, è comune sfruttare il codice di uscita salvandolo in una variabile e usarlo per fornire un output dinamico sullo stato dell’esecuzione:
#!/bin/bash
cp /file_sorgente.txt /cartella_destinazione/
EXIT_STATUS=$?
if [ $EXIT_STATUS -eq 0 ]; then
echo "Copia completata con successo."
else
echo "Errore durante la copia. Codice di uscita: $EXIT_STATUS"
fi
Codici di uscita comuni e convenzioni
Sebbene ogni programma possa definire i propri codici di uscita, esistono alcune convenzioni comuni:
Codice | Significato |
---|---|
0 | Successo. |
1 | Errore generico (catch-all). |
2 | Errore di uso del comando (es. argomenti errati). |
126 | Comando trovato ma non eseguibile (permessi insufficienti). |
127 | Comando non trovato. |
128 + N | Terminazione causata da un segnale POSIX. N è il numero del segnale ricevuto. |
Esempi di codici 128 + N
:
130
= 128 + 2 → interruzione conCtrl+C
(SIGINT
)137
= 128 + 9 → terminazione forzata conkill -9
(SIGKILL
)
Altri codici (da 1
a 255
) possono essere definiti dai singoli programmi per indicare errori specifici. Ad esempio, un programma di backup potrebbe restituire:
10
→ file mancante,11
→ spazio su disco insufficiente.
È buona pratica documentare chiaramente questi codici nei manuali o nella documentazione del programma.
Limiti dei codici di uscita
I codici di uscita sono interi senza segno e, nei sistemi POSIX, sono limitati all’intervallo 0–255
. Se un programma tenta di terminare con un valore superiore (es. exit 300
), verrà restituito solo il valore modulo 256. Esempio:
exit 257 # Risultato effettivo: 1 (perché 257 % 256 = 1)
Gestione dei codici di uscita in Python
Anche in Python, il comportamento dei codici di uscita segue la stessa logica di Unix e del linguaggio C. Quando uno script Python viene eseguito, il processo associato termina restituendo un exit status al sistema operativo, che può essere interpretato da altre applicazioni o script.
Comportamento predefinito degli exit code in Python
- Se lo script Python termina normalmente, senza eccezioni non gestite e senza una chiamata esplicita a
sys.exit()
, il codice di uscita restituito sarà0
, che indica successo. - Se durante l’esecuzione si verifica un’eccezione non gestita, Python stampa lo stack trace e il processo termina con un codice di uscita diverso da 0 (tipicamente
1
,). - Se si chiama
sys.exit(N)
, il programma termina immediatamente con il codiceN
, che può essere qualsiasi intero da0
a255
.
“Dichiarare l’exit code” tramite l’uso esplicito con sys.exit()
Per controllare in modo esplicito il codice di uscita in uno script Python, si utilizza la funzione sys.exit()
, definita nel modulo sys
. Può essere utile per segnalare errori specifici o per interrompere volontariamente il flusso in base a una condizione.
import sys
if not some_condition:
print("Errore: condizione non soddisfatta.")
sys.exit(2) # Codice di errore personalizzato
print("Tutto OK.")
sys.exit(0) # Termine esplicito con successo
Esempi pratici
✅ successo.py
— terminazione corretta
print("Questo script è terminato con successo.")
# Nessuna chiamata a sys.exit() → il codice di uscita sarà 0
❌ errore.py
— errore esplicito
import sys
print("Errore esplicito generato.")
sys.exit(1) # Termine forzato con errore
⚠️ errore_eccezione.py
— eccezione non gestita
print("Questo script genererà un'eccezione.")
x = 1 / 0 # Divisione per zero → eccezione non gestita → codice di uscita ≠ 0
Verifica in una shell Unix/Linux
Se testiamo i tra file Python sopra riportati in una shell con il comando $
…
python successo.py
echo $? # Output: 0
python errore.py
echo $? # Output: 1
python errore_eccezione.py
echo $? # Output: 1
Quindi anche qui potrò sfruttare gli operatori condizionali per rendere le esecuzioni dei miei script più “dinamiche”:
python successo.py && echo "Script completato con successo."
# Output: stampa entrambi i messaggi
python errore.py && echo "Questo messaggio NON verrà stampato."
# Output: solo il messaggio dello script, non quello dopo "&&"
