Use when implementing error handling, cleanup routines, or debugging in shell scripts. Covers traps, exit codes, and robust error patterns.
Limited to specific tools
Additional assets for this skill
This skill is limited to using the following tools:
name: shell-error-handling description: Use when implementing error handling, cleanup routines, or debugging in shell scripts. Covers traps, exit codes, and robust error patterns. allowed-tools:
Patterns for robust error handling, cleanup, and debugging in shell scripts.
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Misuse of shell command |
| 126 | Command not executable |
| 127 | Command not found |
| 128+N | Fatal signal N |
| 130 | Ctrl+C (SIGINT) |
# Check last command's exit status
if ! command; then
echo "Command failed with status $?" >&2
exit 1
fi
# Alternative pattern
command || {
echo "Command failed" >&2
exit 1
}
# Capture exit status
command
status=$?
if (( status != 0 )); then
echo "Failed with status $status" >&2
fi
#!/usr/bin/env bash
set -euo pipefail
cleanup() {
local exit_code=$?
# Remove temporary files
rm -f "$TEMP_FILE" 2>/dev/null || true
exit "$exit_code"
}
trap cleanup EXIT
TEMP_FILE=$(mktemp)
# Script continues...
# cleanup runs automatically on exit
#!/usr/bin/env bash
set -euo pipefail
cleanup() {
echo "Cleaning up..." >&2
rm -rf "$WORK_DIR" 2>/dev/null || true
}
handle_interrupt() {
echo "Interrupted by user" >&2
cleanup
exit 130
}
trap cleanup EXIT
trap handle_interrupt INT TERM
WORK_DIR=$(mktemp -d)
# Preserve original exit code in cleanup
cleanup() {
local exit_code=$?
# Cleanup operations here
rm -f "$temp_file" 2>/dev/null || true
# Restore exit code
exit "$exit_code"
}
# Use || true for optional cleanup
trap 'rm -f "$temp_file" 2>/dev/null || true' EXIT
# Always write errors to stderr
echo "Error: Something went wrong" >&2
# Error function
error() {
echo "Error: $*" >&2
}
# Die function - error and exit
die() {
echo "Fatal: $*" >&2
exit 1
}
# Usage
[[ -f "$config" ]] || die "Config file not found: $config"
#!/usr/bin/env bash
set -euo pipefail
VERBOSE="${VERBOSE:-false}"
log() {
if [[ "$VERBOSE" == "true" ]]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
fi
}
error() {
echo "[ERROR] $*" >&2
}
log "Starting script"
log "Processing file: $file"
# Check required commands exist
require_command() {
command -v "$1" >/dev/null 2>&1 || {
echo "Error: Required command '$1' not found" >&2
exit 1
}
}
require_command jq
require_command curl
require_command shellcheck
# Validate arguments
if [[ $# -lt 2 ]]; then
echo "Usage: $0 <source> <destination>" >&2
exit 1
fi
source_file="$1"
dest_dir="$2"
# Validate file exists
[[ -f "$source_file" ]] || {
echo "Error: Source file not found: $source_file" >&2
exit 1
}
# Validate directory
[[ -d "$dest_dir" ]] || {
echo "Error: Destination directory not found: $dest_dir" >&2
exit 1
}
# Create secure temp file
TEMP_FILE=$(mktemp) || {
echo "Error: Failed to create temp file" >&2
exit 1
}
# Create secure temp directory
TEMP_DIR=$(mktemp -d) || {
echo "Error: Failed to create temp directory" >&2
exit 1
}
# Always clean up
trap 'rm -rf "$TEMP_FILE" "$TEMP_DIR" 2>/dev/null || true' EXIT
#!/usr/bin/env bash
# Enable debug mode via environment variable
if [[ "${DEBUG:-}" == "1" ]]; then
set -x
fi
set -euo pipefail
# Or toggle with a flag
while getopts "d" opt; do
case $opt in
d) set -x ;;
*) echo "Usage: $0 [-d]" >&2; exit 1 ;;
esac
done
# Enable tracing for specific section
set -x
problematic_code
set +x
# Trace with custom PS4
export PS4='+ ${BASH_SOURCE}:${LINENO}: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
set -x
retry() {
local max_attempts="${1:-3}"
local delay="${2:-1}"
shift 2
local cmd=("$@")
local attempt=1
while (( attempt <= max_attempts )); do
if "${cmd[@]}"; then
return 0
fi
echo "Attempt $attempt failed, retrying in ${delay}s..." >&2
sleep "$delay"
(( attempt++ ))
done
echo "All $max_attempts attempts failed" >&2
return 1
}
# Usage
retry 3 5 curl -f "http://example.com/api"
# Try primary, fall back to secondary
get_config() {
if [[ -f "$HOME/.config/myapp/config" ]]; then
cat "$HOME/.config/myapp/config"
elif [[ -f "/etc/myapp/config" ]]; then
cat "/etc/myapp/config"
else
echo "Error: No config file found" >&2
return 1
fi
}