Mestring av Linux-kommandolinjen og Bash-skripting · leksjon

Streng modus med set -euo pipefail

Aktiver feilstoppende oppførsel, og forstå nøyaktig hvilke feil hvert flagg i streng modus fanger opp og overser.

Leksjon 1 av 413 trinn

Streng modus med set -euo pipefail er en gratis leksjon i Mestring av Linux-kommandolinjen og Bash-skripting på CoddyKit. Dette er leksjon 1 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Mestring av Linux-kommandolinjen og Bash-skripting, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Mestring av Linux-kommandolinjen og Bash-skripting inneholder totalt 4 leksjoner.

Hvorfor Bash mislykkes stille som standard

Som standard fortsetter Bash å kjøre selv når kommandoer mislykkes. Dette fører til vanskelige og subtile feil i produksjonsskript.

Se på dette skriptet, som forsøker å opprette en sikkerhetskopi:

  • En skrivefeil i en sti fører til at cp mislykkes
  • Bash ignorerer feilen og fortsetter
  • Skriptet rapporterer at det lyktes, selv om dataene aldri ble sikkerhetskopiert

Dette er problemet med stille feil. Streng modus løser det ved å få Bash til å oppføre seg som et kompilert språk: stoppe umiddelbart når noe 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 viktigste flaggene: set -euo pipefail

Streng modus aktiveres ved å plassere denne linjen nær toppen av hvert skript:

set -euo pipefail

Dette aktiverer tre separate sikkerhetsmekanismer:

  • -e – avslutt umiddelbart hvis en kommando returnerer en status som ikke er null
  • -u – behandle variabler som ikke er satt, som en feil (i stedet for å utvide dem til en tom streng)
  • -o pipefail – en pipeline mislykkes hvis en hvilken som helst kommando i den mislykkes, ikke bare den siste

Sammen utgjør de standardhodet for defensive Bash-skript av høy kvalitet. Hvert flagg fanger opp en egen type feil.

#!/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) gjør at skriptet avsluttes umiddelbart når en kommando avsluttes med en status som ikke er null.

Viktige virkemåter du bør kjenne til:

  • Enkle kommandoer: false, grep pattern file (ingen treff) og ls /nonexistent utløser alle avslutning
  • Avslutningskoden til den siste kommandoen i skriptet blir skriptets avslutningskode
  • Kommandoer i if-betingelser er unntatt – -e utløses ikke for testuttrykket
  • Kommandoer etterfulgt av || true er også unntatt (se de neste scenene)

Se på -e som ditt første forsvar mot å fortsette stille etter en feil.

#!/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) gjør at Bash behandler enhver referanse til en variabel som ikke er satt, som en alvorlig feil.

Uten -u utvides en skrivefeil som $FLENAME i stedet for $FILENAME stille til en tom streng. Det kan føre til at kommandoer oppfører seg uventet – eller farlig (tenk deg rm -rf "$TMPDIR/" når $TMPDIR ikke er satt).

Viktige unntak:

  • ${VAR:-default} – trygg standardverdi, utløser ikke -u
  • ${VAR:+value} – betinget utvidelse, også trygg
  • "$@" og "$*" er unntatt når ingen posisjonsargumenter er angitt
#!/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

Uten pipefail bestemmes avslutningsstatusen til en pipeline utelukkende av den siste kommandoen. Tidligere feil blir svelget i stillhet.

Eksempel uten pipefail:

  • cat /missing/file | wc -l
  • cat mislykkes med avslutningskode 1, men wc -l lykkes med kode 0
  • Pipelinen returnerer 0 – vellykket! Selv om data gikk tapt.

Når pipefail er aktivert, returnerer Bash avslutningskoden til den siste kommandoen som mislyktes. Dette gjør feil i pipelines synlige og mulig å fange opp.

Merk: pipefail er ikke et bokstavflagg – det må angis 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"

Bevisste kommandofeil – bruk av || true

Noen ganger er det tillatt at en kommando mislykkes. Med set -e må du uttrykkelig angi hvilke feil som skal tolereres; ellers avbrytes skriptet.

Den idiomatiske løsningen er || true, som legger til en reservehandling som alltid lykkes:

  • command || true – ignorer feilen fullstendig
  • command || echo "Warning: step failed, continuing" – logg feilen og fortsett
  • command || { echo "fatal"; exit 1; } – egendefinert feilhåndtering

Dette mønsteret gjør hensikten tydelig i koden: En vanlig kommando betyr «dette må lykkes», mens || true betyr «dette kan mislykkes, og det er greit».

#!/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"

Hva set -e IKKE fanger opp

set -e har kjente unntak og fallgruver. Når du forstår dem, unngår du falsk trygghet:

  • Kommandoer i if- / while- / until-betingelser – testuttrykket er med hensikt unntatt
  • Kommandoer negert med ! – ! false utløser ikke avslutning
  • Den siste kommandoen før || – for eksempel false || handle_error
  • Avslutningsstatusen til subshells i visse sammenhenger – for eksempel VAR=$(failing_command) i enkelte Bash-versjoner
  • Returverdier fra funksjoner – bare den siste kommandoen i en funksjon teller

Streng modus erstatter ikke eksplisitt feilsjekking – det er et sikkerhetsnett som fanger opp de fleste utilsiktede feil.

#!/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 funksjoner med streng modus

Innstillinger for streng modus arves av subshells, men oppfører seg noe annerledes i funksjoner og kommandosubstitusjoner.

Viktige regler:

  • Funksjoner arver -e, -u og pipefail fra skallet som kaller dem
  • En funksjon som returnerer en verdi som ikke er null, fører til at det kallende skallet avsluttes (når -e er satt) – med mindre kallet inngår i en betingelse eller står etter ||
  • Kommandosubstitusjon $(): I eldre Bash-versjoner utløser en kommando som mislykkes inne i $(), kanskje ikke -e i det overordnede skallet; tilordne resultatet og bruk det separat for å være på den sikre siden
  • Eksplisitte subshells () arver alle flaggene
#!/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"

Kombinere streng modus med feilhåndtering

Streng modus forteller Bash når det skal stoppe. Med en trap på ERR kan du kjøre opprydding eller diagnostikk før skriptet avsluttes.

Det vanlige mønsteret er:

  • Aktiver streng modus øverst i skriptet
  • Definer en cleanup- eller on_error-funksjon
  • Registrer den med trap 'on_error' ERR
  • Du kan også registrere en EXIT-felle for garantert opprydding, uavhengig av om skriptet lykkes eller mislykkes

Viktig: Bruk set -E (stor E, også kalt errtrace) slik at ERR-fellen også arves av funksjoner og subshells – uten dette utløses feller bare i hovedskallets hoveddel.

#!/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"

Deaktivere streng modus lokalt

Noen ganger er en kodeblokk med hensikt «rotete» – for eksempel når du undersøker om valgfrie verktøy finnes, eller kjører eldre kommandoer som returnerer en status som ikke er null av grunner som ikke skyldes feil. Du kan deaktivere streng modus midlertidig og aktivere den igjen etterpå.

Det sikre mønsteret:

  • Lagre tilstanden med set +e (deaktiverer -e), kjør blokken og aktiver deretter set -e igjen
  • Eller bruk en subshell ( set +e; ... ), slik at flaggene i det overordnede skallet aldri påvirkes
  • Aktiver alltid flaggene igjen så snart den risikable blokken er ferdig – det er en vanlig kilde til feil å la flaggene være deaktivert

Foretrekk subshell-varianten når blokken inneholder flere kommandoer, siden den automatisk gjenoppretter flaggene ved avslutning.

#!/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 komplett skriptmal for streng modus

Her er en produksjonsklar mal som samler alle anbefalte fremgangsmåter for streng modus som er gjennomgått i denne leksjonen:

  • set -Eeuo pipefail – alle fire flaggene, inkludert errtrace
  • IFS=$'\n\t' – tryggere orddeling (unngår deling ved mellomrom)
  • ERR- og EXIT-feller for diagnostikk og opprydding
  • Eksplisitte standardverdier for valgfrie parametere
  • readonly og local for å begrense variablenes omfang

Kopier denne malen inn i starten av alle Bash-skript som ikke er helt trivielle, slik at du umiddelbart får fordelene ved å stoppe raskt ved feil og få sporbare feil.

#!/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 "$@"

Kunnskapssjekk: pipefail-atferd

Test forståelsen Deres av hvordan pipefail påvirker avslutningskoder for pipelines.

Oppsummering: Strict mode med set -euo pipefail

I denne leksjonen lærte De hvordan Bash-skript kan avslutte raskt og tydelig ved hjelp av strict mode.

De tre flaggene og hva de beskytter mot:

  • -e (errexit) — avslutter ved enhver kommando med status ulik null; unntatt i betingelser og etter ||
  • -u (nounset) — avbryter ved referanser til variabler som ikke er satt; bruk ${VAR:-default} for valgfrie variabler
  • -o pipefail — får en hel pipeline til å mislykkes hvis et hvilket som helst trinn mislykkes, ikke bare det siste

Supplerende praksiser:

  • Legg til -E (errtrace) slik at ERR-feller videreføres til funksjoner
  • Bruk trap på ERR og EXIT for diagnostikk og opprydding
  • Bruk || true for å tolerere feil med hensikt
  • Deaktiver midlertidig med set +e i subshells for eldre kode eller sonderingskode

Strict mode er ingen mirakelkur — De må kjenne unntakene — men det er den enkeltstående mest effektive vanen for å skrive pålitelige og defensive Bash-skript.

Gratis å komme i gang

Lær deg Bash med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
22
Leksjoner
88

Ofte stilte spørsmål

Er leksjonen «Streng modus med set -euo pipefail» gratis?

Ja – hele teksten i «Streng modus med set -euo pipefail» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Mestring av Linux-kommandolinjen og Bash-skripting-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Mestring av Linux-kommandolinjen og Bash-skripting inneholder totalt 4 leksjoner.

Hva lærer jeg i «Streng modus med set -euo pipefail»?

Aktiver feilstoppende oppførsel, og forstå nøyaktig hvilke feil hvert flagg i streng modus fanger opp og overser. Du øver på Mestring av Linux-kommandolinjen og Bash-skripting med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Mestring av Linux-kommandolinjen og Bash-skripting?

Ingen tidligere erfaring er nødvendig. Mestring av Linux-kommandolinjen og Bash-skripting på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 1 av 4.

Hvor lang tid tar leksjonen «Streng modus med set -euo pipefail»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Mestring av Linux-kommandolinjen og Bash-skripting-leksjonen?

Ja. Alle Mestring av Linux-kommandolinjen og Bash-skripting-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Streng modus med set -euo pipefail
  2. Trap-behandlere for opprydding og signaler
  3. Sikre midlertidige filer og låsekataloger
  4. Idempotente skript og retry-logikk med backoff
← Tilbake til Mestring av Linux-kommandolinjen og Bash-skripting