Przejdź do treści

❗ Error Handling

Error handling in POSIX shells is subtle and often misunderstood. Shells do not fail fast by default, pipelines hide errors, and subshells discard state. This module provides practical techniques for writing reliable, production‑grade scripts.


🎓 Who This Is For

  • Engineers writing automation or CI/CD pipelines
  • DevOps/SRE teams maintaining production scripts
  • Developers migrating from bash to POSIX sh
  • Anyone needing predictable failure behavior

🧩 Role in the Ecosystem

Shells provide minimal built‑in error handling. Correctness depends on:

  • Exit codes
  • Conditional checks
  • Traps
  • Strict mode (bash/ksh)
  • Defensive programming

This module complements Traps & Signals and Debugging Scripts.


🧩 Key Concepts

1. Exit Codes

Commands return 0 on success, non‑zero on failure.

2. Conditional Execution

1
2
command || exit 1
command && echo ok

3. set -e (bash/ksh)

Stops execution on unhandled errors — but with many exceptions.

4. pipefail

Ensures pipelines fail if any stage fails.

5. Traps

Used for cleanup and controlled shutdown.


🔧 Techniques

Explicit Error Checks

1
2
3
4
if ! command; then
  echo "failed" >&2
  exit 1
fi

Strict Mode (bash/ksh)

1
set -euo pipefail

POSIX‑Safe Error Handling

1
2
3
4
command || {
  echo "error: command failed" >&2
  exit 1
}

Required Variables

1
: "${TOKEN:?TOKEN is required}"

Cleanup on Error

1
trap 'rm -f "$TMPFILE"' EXIT

Fail Fast in Pipelines

1
set -o pipefail

⚠️ Limitations & Pitfalls

  • set -e does not work reliably in POSIX sh
  • Pipelines hide failures without pipefail
  • Subshells discard variable changes
  • Traps behave differently across shells
  • Error messages printed to stdout break scripts
  • Bash‑only features break portability

🧠 When to Use These Techniques

  • Writing robust automation
  • Handling temporary files or resources
  • Ensuring CI/CD stops on failure
  • Validating required configuration
  • Preventing silent data corruption

❌ When Not to Use Them

  • Extremely small scripts
  • Legacy scripts relying on implicit behavior
  • Highly portable /bin/sh scripts requiring strict POSIX compliance
  • Scripts where partial failure is acceptable

✅ Best Practices

  • Always check exit codes explicitly
  • Use set -euo pipefail in bash/ksh scripts
  • Use traps for cleanup
  • Print errors to stderr:
1
echo "error" >&2
  • Avoid complex logic inside traps
  • Keep error messages consistent and machine‑parsable
  • Test under multiple shells

🧪 Testing Error Handling

1
2
3
set -e
false
echo "unreachable"

Test pipeline behavior:

1
2
3
set -o pipefail
false | true
echo $?   # 1

Test required variables:

1
: "${TOKEN:?missing TOKEN}"

🧠 Summary

Error handling in shell scripts requires explicit checks, strict mode, traps, and defensive programming. Used correctly, these techniques prevent silent failures and make automation predictable and safe.