shell-error-handling

Patterns for robust error handling, cleanup, and debugging in shell scripts.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "shell-error-handling" with this command: npx skills add thebushidocollective/han/thebushidocollective-han-shell-error-handling

Shell Error Handling

Patterns for robust error handling, cleanup, and debugging in shell scripts.

Exit Codes

Standard Exit Codes

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)

Checking Exit Status

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

Trap for Cleanup

Basic Cleanup Pattern

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

Handling Multiple Signals

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

Trap Best Practices

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

Error Reporting

Standard Error Output

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"

Verbose Logging

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

Defensive Programming

Check Prerequisites

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 Input

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 }

Safe Temporary Files

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

Debugging

Debug Mode

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

Trace Execution

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

Error Recovery Patterns

Retry Pattern

retry() { local max_attempts="${1:-3}" local delay="${2:-1}" shift 2 local cmd=("$@")

local attempt=1
while (( attempt &#x3C;= max_attempts )); do
    if "${cmd[@]}"; then
        return 0
    fi
    echo "Attempt $attempt failed, retrying in ${delay}s..." >&#x26;2
    sleep "$delay"
    (( attempt++ ))
done

echo "All $max_attempts attempts failed" >&#x26;2
return 1

}

Usage

retry 3 5 curl -f "http://example.com/api"

Fallback Pattern

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 }

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

android-jetpack-compose

No summary provided by upstream source.

Repository SourceNeeds Review
General

fastapi-async-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

storybook-story-writing

No summary provided by upstream source.

Repository SourceNeeds Review