set -euo pipefail în Linux / Bash

Scripting Bash POSIX (-e, -u) / Bash 3.0 (pipefail)

Face un script Bash să se oprească la prima eroare, la variabile nedefinite și la comenzi eșuate din pipeline.

Sintaxă comandă
set -euo pipefail
set -e    set -u    set -o pipefail    set -x

Ce face set -euo pipefail

Implicit, Bash continuă după o comandă care eșuează. Rândul set -euo pipefail de la începutul scriptului schimbă asta: -e oprește scriptul când o comandă întoarce un cod diferit de 0, -u tratează folosirea unei variabile nedefinite ca eroare, iar -o pipefail face ca un pipeline să eșueze dacă eșuează oricare dintre comenzile lui, nu doar ultima.

set -e are excepții: nu oprește scriptul pentru comenzile din condiția unui if sau while, pentru cele urmate de && / || și pentru cele negate cu !. Așa poți testa o comandă care ar putea eșua fără să oprești scriptul.

Pentru depanare, set -x afișează fiecare comandă înainte de execuție, precedată de +. Opțiunile se dezactivează cu +: set +e, set +x.

Opțiuni și argumente

Opțiune / Parametru Descriere
-e (errexit) Ieșire imediată când o comandă eșuează.
-u (nounset) Eroare la folosirea unei variabile nedefinite; ${VAR:-implicit} rămâne permis.
-o pipefail Codul unui pipeline este al ultimei comenzi care a eșuat.
-x (xtrace) Afișează comenzile pe măsură ce rulează, pentru depanare.
set +e Dezactivează temporar oprirea la eroare.

Exemple

Exemplul 1: Efectul lui pipefail

Fără pipefail, codul pipeline-ului este al lui true (0). Cu pipefail, eșecul lui false se vede.

false | true
echo "Fără pipefail: $?"
set -o pipefail
false | true || echo "Cu pipefail: $?"

Rezultat

Fără pipefail: 0
Cu pipefail: 1

Exemplul 2: set -u și valorile implicite

Variabila nedefinită oprește subshell-ul, dar ${ORAS:-necunoscut} funcționează și cu set -u.

set -u
NUME="Ana"
echo "Salut, $NUME"
echo "Oraș: ${ORAS:-necunoscut}"
if ( echo "$PRENUME" ) 2>/dev/null; then
  echo "Nu se ajunge aici"
else
  echo "set -u a oprit subshell-ul: PRENUME nu este definit"
fi

Rezultat

Salut, Ana
Oraș: necunoscut
set -u a oprit subshell-ul: PRENUME nu este definit

Exemplul 3: Un script de backup care se oprește la eroare

Copierea eșuează, deci pasul 2 nu mai rulează. Codul de ieșire al scriptului este cel al lui cp.

cat > backup.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
echo "Pasul 1: copiez fișierele"
cp facturi_lipsa.csv arhiva/
echo "Pasul 2: nu se mai execută"
EOF
bash backup.sh 2>/dev/null || echo "Scriptul s-a oprit cu codul $?"

Rezultat

Pasul 1: copiez fișierele
Scriptul s-a oprit cu codul 1

Greșeli frecvente

  • (( contor++ )) cu contor=0 sub set -e: expresia valorează 0, deci comanda întoarce 1 și scriptul se oprește. Folosește (( contor += 1 )) sau contor=$((contor + 1)).
  • Încrederea totală în set -e: nu se aplică în funcțiile apelate dintr-un if sau înainte de ||. Verifică explicit comenzile importante.
  • grep care nu găsește nimic întoarce 1 și oprește scriptul sub set -e. Dacă lipsa rezultatelor este normală, scrie grep ... || true.

Comenzi înrudite

  • Coduri de ieșire ($?, &&, ||): Fiecare comandă întoarce un cod: 0 pentru succes, 1-255 pentru eroare. Se citește cu $? și se folosește cu && și ||.
  • trap: Rulează comenzi când scriptul primește un semnal (INT, TERM) sau la ieșire (EXIT), de obicei pentru curățenie.
  • exit: Încheie execuția shell-ului sau a scriptului curent și transmite un cod numeric de stare sistemului.
  • Variabile în Bash: Declararea, atribuirea, valorile implicite și expandarea corectă a variabilelor în Bash.