Intensiv DevOps-uddannelse · Lektion

Streng tilstand med set -euo pipefail

Aktivér fail-fast-adfærd, og forstå præcist, hvilke fejl hver strengtilstandsflag fanger eller ikke fanger.

Lektion 1 af 413 trin

Streng tilstand med set -euo pipefail er en gratis Intensiv DevOps-uddannelse-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Intensiv DevOps-uddannelse, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.

Hvorfor Bash som standard fejler lydløst

Som standard fortsætter Bash med at køre, selv når kommandoer mislykkes. Det fører til vanskelige, svære at fejlfinde katastrofer i produktionsskripter.

Overvej dette script, der forsøger at oprette en sikkerhedskopi:

  • En slåfejl i en sti får cp til at mislykkes
  • Bash ignorerer fejlen og fortsætter
  • Scriptet melder om succes, selv om data aldrig blev sikkerhedskopieret

Dette er problemet med lydløse fejl. Strikt tilstand løser det ved at få Bash til at opføre sig som et kompileret sprog: stoppe med det samme, når noget går galt.

#!/usr/bin/env bash
# Without strict mode — dangerous default behavior

cp /important/data /backups/data   # fails (path doesn't exist)
echo "Backup complete"              # still prints — false confidence!
rm -rf /tmp/staging                # still runs — potentially destructive

De tre centrale flag: set -euo pipefail

Strikt tilstand aktiveres ved at placere denne linje nær toppen af hvert script:

set -euo pipefail

Det aktiverer tre forskellige sikkerhedsværn:

  • -e — Afslut med det samme, hvis en kommando returnerer en status, der ikke er nul
  • -u — Behandl variabler uden værdi som en fejl (i stedet for at udvide dem til en tom streng)
  • -o pipefail — En pipeline mislykkes, hvis en hvilken som helst kommando i den mislykkes, ikke kun den sidste

Tilsammen udgør de den standardmæssige defensive header til seriøse Bash-skripter. Hvert flag fanger en forskellig klasse af fejl.

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

echo "Strict mode is now active"
echo "Every command failure will abort the script"

Forstå set -e (errexit)

set -e (også skrevet som set -o errexit) får scriptet til at afslutte med det samme, når en kommando afslutter med en status, der ikke er nul.

Vigtige egenskaber, du bør kende:

  • Simple kommandoer: false, grep pattern file (intet match), ls /nonexistent udløser alle afslutning
  • Den sidste kommandos exitkode i scriptet bliver scriptets exitkode
  • Kommandoer i if-betingelser er undtaget — -e udløses ikke for testudtrykket
  • Kommandoer efterfulgt af || true er også undtaget (se de næste scener)

Tænk på -e som din første forsvarslinje mod at fortsætte lydløst efter en fejl.

#!/usr/bin/env bash
set -e

echo "Before failure"
ls /this/path/does/not/exist   # exits here with code 2
echo "This line never runs"

Forstå set -u (nounset)

set -u (også skrevet som set -o nounset) får Bash til at behandle enhver reference til en variabel uden værdi som en fatal fejl.

Uden -u udvides en slåfejl som $FLENAME i stedet for $FILENAME lydløst til en tom streng, så kommandoer opfører sig uventet — eller farligt (forestil dig rm -rf "$TMPDIR/", når $TMPDIR ikke er sat).

Vigtige undtagelser:

  • ${VAR:-default} — sikker substitution med standardværdi, der ikke udløser -u
  • ${VAR:+value} — betinget udvidelse, også sikker
  • "$@" og "$*" er undtaget, når der ikke er angivet positionsargumenter
#!/usr/bin/env bash
set -euo pipefail

# Safe: provide a default for optional vars
OUTPUT_DIR="${1:-/tmp/output}"
LOG_LEVEL="${LOG_LEVEL:-info}"

echo "Writing to: $OUTPUT_DIR"
echo "Log level: $LOG_LEVEL"

# This would abort the script:
# echo "$UNDEFINED_VAR"   # bash: UNDEFINED_VAR: unbound variable

Forstå -o pipefail

Uden pipefail bestemmes en pipelines exitstatus udelukkende af den sidste kommando. Tidligere fejl sluges lydløst.

Eksempel uden pipefail:

  • cat /missing/file | wc -l
  • cat mislykkes med exitkode 1, men wc -l lykkes med kode 0
  • Pipelinen returnerer 0 — succes! Selvom data gik tabt.

Når pipefail er aktiveret, returnerer Bash exitkoden fra den sidste kommando fra højre, der mislykkedes. Det gør fejl i pipelines synlige og mulige at håndtere.

Bemærk: pipefail er ikke et bogstavflag — det skal sættes med -o pipefail.

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

# With pipefail: this aborts if grep finds nothing (exit 1)
# grep returns 1 when no match found
ps aux | grep "[n]ginx" | awk '{print $2}'

echo "If we reach here, nginx is running"

Bevidste kommandofejl — brug af || true

Nogle gange må en kommando gerne mislykkes. Med set -e skal du udtrykkeligt angive fejl, der accepteres; ellers afbrydes scriptet.

Den idiomatiske løsning er || true, som tilføjer en fallback, der altid lykkes:

  • command || true — ignorér fejlen fuldstændigt
  • command || echo "Warning: step failed, continuing" — log fejlen, og fortsæt
  • command || { echo "fatal"; exit 1; } — brugerdefineret fejlhåndtering

Dette mønster gør din hensigt tydelig i koden: En almindelig kommando betyder "dette skal lykkes"; || true betyder "dette må mislykkes, og det er i orden".

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

# Remove temp dir if it exists — OK if it doesn't
rm -rf /tmp/my_workspace || true
mkdir -p /tmp/my_workspace

# Check if a service is running — OK if not
if systemctl is-active --quiet nginx 2>/dev/null || true; then
  echo "nginx is active"
fi

# Grep that may find nothing — OK
grep 'ERROR' /var/log/app.log || true

echo "Done"

Hvad set -e IKKE fanger

set -e har velkendte undtagelser og faldgruber. Når du forstår dem, undgår du falsk tryghed:

  • Kommandoer i betingelser med if / while / until — testudtrykket er med vilje undtaget
  • Kommandoer negeret med ! — ! false udløser ikke en afslutning
  • Den sidste kommando før || — f.eks. false || handle_error
  • Exitstatus for subshells i bestemte sammenhænge — f.eks. VAR=$(failing_command) i visse Bash-versioner
  • Funktioners returværdier — kun den sidste kommando i en funktion tæller

Strikt tilstand er ikke en erstatning for eksplicit fejlkontrol — det er et sikkerhedsnet, der fanger størstedelen af utilsigtede fejl.

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

# These do NOT trigger -e:
if false; then echo "never"; fi         # -e exempt in conditions
! false                                  # negation exempts
false || echo "handled"                 # || exempts the left side

# This DOES trigger -e (no condition, no ||):
# false

echo "Script continues after exempted failures"

Subshells og funktioner i strikt tilstand

Indstillinger for strikt tilstand nedarves af subshells, men opfører sig subtilt i funktioner og kommandosubstitutioner.

Vigtige regler:

  • Funktioner arver -e, -u og pipefail fra det kaldende shell
  • En funktion, der returnerer en status, der ikke er nul, får det kaldende shell til at afslutte (når -e er sat) — medmindre kaldet indgår i en betingelse eller står efter ||
  • Kommandosubstitution $(): I ældre Bash kan en fejlende kommando i $() muligvis ikke udløse -e i det overordnede shell; tildel resultatet, og brug det derefter separat for at være på den sikre side
  • Eksplicitte subshells () arver alle flag
#!/usr/bin/env bash
set -euo pipefail

setup_workspace() {
  local dir="$1"
  mkdir -p "$dir"          # fails here if permissions denied
  cd "$dir"
  echo "Ready in $(pwd)"
}

# Safe pattern: assign result then use it
TODAY=$(date +%Y-%m-%d)   # capture separately
WORKDIR="/tmp/run_${TODAY}"

setup_workspace "$WORKDIR"
echo "Workspace: $WORKDIR"

Kombinér strikt tilstand med fejlfangst

Strikt tilstand fortæller Bash hvornår det skal stoppe. En trap på ERR lader dig udføre oprydning eller diagnosticering, før scriptet afsluttes.

Det almindelige mønster er:

  • Angiv strikt tilstand øverst
  • Definér en funktion til cleanup eller on_error
  • Registrér den med trap 'on_error' ERR
  • Du kan også fange EXIT for at sikre oprydning uanset succes eller fejl

Vigtigt: Brug set -E (stort E, også kaldet errtrace), så ERR-fangsten også nedarves af funktioner og subshells — uden dette udløses fangster kun i hoveddelen af shell'et.

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

on_error() {
  local exit_code=$?
  local line_number=${BASH_LINENO[0]}
  echo "ERROR: command failed with code ${exit_code} at line ${line_number}" >&2
}

cleanup() {
  echo "Cleaning up temporary files..." >&2
  rm -rf /tmp/my_run_dir 2>/dev/null || true
}

trap on_error ERR
trap cleanup EXIT

mkdir -p /tmp/my_run_dir
echo "hello" > /tmp/my_run_dir/output.txt
cat /tmp/my_run_dir/output.txt
echo "Done"

Deaktivér strikt tilstand lokalt

Nogle gange er en kodeblok med vilje "rodet" — f.eks. når du undersøger, om valgfrie værktøjer findes, eller kører ældre kommandoer, der returnerer en status, der ikke er nul, uden at det skyldes en fejl. Du kan midlertidigt deaktivere strikt tilstand og gendanne den bagefter.

Det sikre mønster:

  • Gem tilstanden med set +e (deaktiverer -e), kør blokken, og aktivér derefter igen med set -e
  • Eller brug et subshell ( set +e; ... ), så det overordnede shells flag aldrig påvirkes
  • Aktivér altid flagene igen, så snart den risikable blok er afsluttet — det er en almindelig kilde til fejl at lade flagene være deaktiveret

Foretræk subshell-formen, når blokken indeholder flere kommandoer, da den automatisk gendanner flagene ved afslutning.

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

# Probe for optional tools without aborting
HAS_JQ=false
(
  set +e
  command -v jq > /dev/null 2>&1
  [[ $? -eq 0 ]] && echo "jq_found"
) && HAS_JQ=true || true

if [[ "$HAS_JQ" == "true" ]]; then
  echo "jq is available — using JSON output"
else
  echo "jq not found — using plain text"
fi

En komplet skabelon til et script med strikt tilstand

Her er en produktionsklar skabelon, der samler alle de bedste fremgangsmåder for strikt tilstand, som er gennemgået i denne lektion:

  • set -Eeuo pipefail — alle fire flag, inklusive errtrace
  • IFS=$'\n\t' — sikrere ordopdeling (undgår opdeling ved mellemrum)
  • ERR- og EXIT-fangster til diagnosticering og oprydning
  • Eksplicitte standardværdier for valgfrie parametre
  • readonly og local til at begrænse variablers synlighed

Kopiér denne skabelon i begyndelsen af hvert ikke-trivielt Bash-script for straks at få fordel af fejlhurtig adfærd og fejl, der kan spores.

#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'

# ── Constants ────────────────────────────────────────────
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "$0")"

# ── Trap handlers ────────────────────────────────────────
err_handler() {
  echo "[${SCRIPT_NAME}] ERROR on line ${BASH_LINENO[0]}: exit ${?}" >&2
}
cleanup() {
  echo "[${SCRIPT_NAME}] Exiting" >&2
}
trap err_handler ERR
trap cleanup EXIT

# ── Defaults ─────────────────────────────────────────────
ENV="${1:-production}"
MAX_RETRIES="${MAX_RETRIES:-3}"

# ── Main ─────────────────────────────────────────────────
main() {
  echo "Running in env=${ENV}, max_retries=${MAX_RETRIES}"
  echo "Script dir: ${SCRIPT_DIR}"
}

main "$@"

Videnstjek: pipefail-adfærd

Test din forståelse af, hvordan pipefail påvirker pipelines afslutningskoder.

Opsummering: Strict mode med set -euo pipefail

I denne lektion lærte du, hvordan du får Bash-scripts til at fejle hurtigt og tydeligt ved hjælp af strict mode.

De tre flag, og hvad de beskytter mod:

  • -e (errexit) — afslutter ved enhver kommando-status, der ikke er nul; undtages i betingelser og efter ||
  • -u (nounset) — afbryder ved referencer til variabler, der ikke er sat; brug ${VAR:-default} til valgfrie variabler
  • -o pipefail — får en hel pipeline til at fejle, hvis et trin fejler, ikke kun det sidste

Supplerende praksisser:

  • Tilføj -E (errtrace), så ERR-traps føres videre til funktioner
  • Brug trap på ERR og EXIT til diagnosticering og oprydning
  • Brug || true til bevidst at acceptere fejl
  • Deaktivér midlertidigt med set +e i subshells til ældre kode eller sonderingskode

Strict mode er ikke en mirakelkur — du skal kende undtagelserne — men det er den mest effektive enkeltstående vane til at skrive pålidelige og defensive Bash-scripts.

Gratis at komme i gang

Lær Intensiv DevOps-uddannelse med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
142
Lektioner
568

Ofte stillede spørgsmål

Er lektionen “Streng tilstand med set -euo pipefail” gratis?

Ja — alle 3 lektioner i læringssporet Intensiv DevOps-uddannelse, inklusive “Streng tilstand med set -euo pipefail”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Streng tilstand med set -euo pipefail”?

Aktivér fail-fast-adfærd, og forstå præcist, hvilke fejl hver strengtilstandsflag fanger eller ikke fanger. Du øver dig i Intensiv DevOps-uddannelse med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Intensiv DevOps-uddannelse?

Der kræves ingen tidligere erfaring. Intensiv DevOps-uddannelse på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.

Hvor lang tid tager lektionen “Streng tilstand med set -euo pipefail”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Intensiv DevOps-uddannelse-lektion?

Ja. Alle Intensiv DevOps-uddannelse-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Streng tilstand med set -euo pipefail
  2. Trap-håndteringer til oprydning og signaler
  3. Sikre midlertidige filer og låsem mapper
  4. Idempotente scripts og retry-logik med backoff
← Tilbage til Intensiv DevOps-uddannelse