CodeToLive

Bash Debugging & Error Handling

Effective debugging and error handling are essential for writing robust Bash scripts. This tutorial covers techniques to identify and resolve issues in your scripts.

Debugging Options

Bash provides several options for debugging:


# Run script with debug output
bash -x script.sh

# Enable debugging within script
set -x  # Enable debugging
# ... script commands ...
set +x  # Disable debugging

# Print commands before execution
set -v
# ... script commands ...
set +v

# Combine both
set -xv
      

Shebang Debugging

You can enable debugging directly in the shebang line:


#!/bin/bash -x
      

PS4 Variable

Customize debug output with the PS4 variable:


export PS4='+ $LINENO: '  # Show line numbers in debug output
set -x
# ... script commands ...
      

Error Handling Options


# Exit immediately if a command fails
set -e

# Exit if any command in a pipeline fails
set -o pipefail

# Treat unset variables as errors
set -u

# Combine all
set -euo pipefail
      

Trap Command

Use trap to catch signals and errors:


# Cleanup function
cleanup() {
    echo "Cleaning up..."
    rm -f tempfile
}

# Trap EXIT signal
trap cleanup EXIT

# Trap ERR signal
trap 'echo "Error on line $LINENO"; exit 1' ERR

# Trap specific signals
trap 'echo "Interrupted!"; exit 1' INT TERM
      

Logging Functions


# Logging function with timestamp
log() {
    local level=$1
    local message=$2
    echo "$(date '+%Y-%m-%d %H:%M:%S') [$level] $message"
}

log "INFO" "Starting script execution"

# Usage in error handling
command || log "ERROR" "Command failed"
      

Debugging Techniques


# Print variable values
echo "DEBUG: var1=$var1, var2=$var2"

# Check function arguments
myfunc() {
    echo "DEBUG: Function called with $# arguments: $@"
    # ... function code ...
}

# Step through script
read -p "Press enter to continue"  # Add breakpoints
      

Error Handling Patterns


# Check command success
if ! command; then
    echo "Command failed" >&2
    exit 1
fi

# Check file existence
if [[ ! -f "$file" ]]; then
    echo "File not found: $file" >&2
    exit 1
fi

# Check directory writable
if [[ ! -w "$dir" ]]; then
    echo "Directory not writable: $dir" >&2
    exit 1
fi
      

Advanced Debugging Tools

External tools for debugging Bash scripts:

Best Practices

Complete Example


#!/bin/bash

# Strict mode
set -euo pipefail

# Configuration
LOG_FILE="script.log"
TEMP_FILE="temp.txt"

# Logging function
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1: $2" | tee -a "$LOG_FILE"
}

# Cleanup function
cleanup() {
    if [[ -f "$TEMP_FILE" ]]; then
        log "INFO" "Removing temporary file"
        rm -f "$TEMP_FILE"
    fi
}

# Trap signals
trap cleanup EXIT
trap 'log "ERROR" "Script interrupted"; exit 1' INT TERM
trap 'log "ERROR" "Error on line $LINENO"; exit 1' ERR

# Main script
log "INFO" "Starting script execution"

# Check arguments
if [[ $# -eq 0 ]]; then
    log "ERROR" "No arguments provided"
    exit 1
fi

input_file="$1"

# Check input file
if [[ ! -f "$input_file" ]]; then
    log "ERROR" "Input file not found: $input_file"
    exit 1
fi

# Process file
log "INFO" "Processing file: $input_file"
grep "important" "$input_file" > "$TEMP_FILE" || {
    log "WARNING" "No matches found in $input_file"
    exit 0
}

# Continue processing
count=$(wc -l < "$TEMP_FILE")
log "INFO" "Found $count important items"

# Final message
log "INFO" "Script completed successfully"
exit 0
      
Next: Advanced Bash Scripting