G
GuideDevOps
Lesson 11 of 15

Error Handling & Exit Codes

Part of the Shell Scripting (Bash) tutorial series.

Exit Codes

Understanding Exit Codes

Every command returns an exit code (0 for success, non-zero for failure):

# Check exit code of last command
ls /tmp
echo "Exit code: $?"         # 0 if success
 
# Failed command
ls /nonexistent
echo "Exit code: $?"         # Non-zero if failed

Custom Exit Codes

if [ ! -f "$1" ]; then
    echo "Error: File not found"
    exit 1
fi
 
if [ ! -r "$1" ]; then
    echo "Error: File not readable"
    exit 2
fi
 
echo "File processed successfully"
exit 0

Check Command Success

# Check immediately after command
command
if [ $? -ne 0 ]; then
    echo "Error occurred"
    exit 1
fi
 
# Direct check
if ! command; then
    echo "Command failed"
    exit 1
fi
 
# Using || (OR)
command || exit 1

set Error Options

#!/bin/bash
 
# Exit on any error
set -e
 
# Also on undefined variables
set -u
 
# Fail on pipe errors
set -o pipefail
 
# Or combine
set -euo pipefail

Error Reporting

Error Function

error() {
    echo "ERROR: $*" >&2
    exit 1
}
 
if [ ! -f "config.txt" ]; then
    error "Config file not found"
fi

With Line Numbers

error() {
    local linenum=$1
    local msg=$2
    echo "ERROR at line $linenum: $msg" >&2
    exit 1
}
 
if [ $? -ne 0 ]; then
    error $LINENO "Previous command failed"
fi

trap - Cleanup on Exit

#!/bin/bash
 
# Create temp file
tmpfile=$(mktemp)
 
# Ensure cleanup on exit
trap "rm -f $tmpfile" EXIT
 
echo "Processing..."
 
# tmpfile automatically removed on exit

Multiple Traps

cleanup() {
    echo "Cleaning up..."
    rm -f temp_files/*
    pkill -f "background_process"
}
 
error_handler() {
    echo "Error on line $1"
    cleanup
    exit 1
}
 
trap "error_handler $LINENO" ERR
trap cleanup EXIT
 
echo "Starting script"

Debugging

Debug Mode

# Run with debugging
bash -x script.sh
 
# Set debug in script
set -x          # Enable
set +x          # Disable
 
# Or use shopt
shopt -s extdebug

Debug PS4 Prompt

# Show filename and line
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
set -x

Conditional Debugging

# Enable debug mode if DEBUG env var set
[ "$DEBUG" = "1" ] && set -x
 
# Then run: DEBUG=1 ./script.sh

Try-Catch Pattern

# Simulate try-catch
try() {
    [[ $- = *e* ]]; SAVED_OPT_E=$?
    set +e
}
 
catch() {
    export exception_code=$?
    (( SAVED_OPT_E )) && set +e
    return $exception_code
}
 
try
(
    risky_command
    another_command
)
catch || {
    echo "Error: Commands failed with code $exception_code"
}

Validation

# Validate arguments
if [ $# -lt 2 ]; then
    echo "Usage: $0 source destination" >&2
    exit 1
fi
 
if [ ! -f "$1" ]; then
    echo "Error: Source file not found: $1" >&2
    exit 1
fi
 
if [ -z "$2" ]; then
    echo "Error: Destination cannot be empty" >&2
    exit 1
fi

Recovery Strategies

# Retry logic
retry_command() {
    local max_attempts=3
    local count=0
    while [ $count -lt $max_attempts ]; do
        if "$@"; then
            return 0
        fi
        ((count++))
        echo "Attempt $count failed, retrying..."
        sleep 2
    done
    return 1
}
 
if ! retry_command curl https://example.com; then
    echo "Failed after $max_attempts attempts"
    exit 1
fi

title: "Error Handling & Exit Codes" description: "Placeholder content for the Error Handling & Exit Codes lesson within the Shell Scripting (Bash) tutorial series." order: 10

Overview

Welcome to the Error Handling & Exit Codes lesson! This topic covers the essential fundamentals and practical applications within the Shell Scripting (Bash) ecosystem.

What You Will Learn

  1. Key terminology and core concepts.
  2. Industry best practices.
  3. Command line operations and configuration.

Example Code

Here is a quick placeholder snippet:

# Error Handling & Exit Codes
echo "Learning Shell Scripting (Bash) at GuideDevOps!"