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:
- shellcheck: Static analysis tool for shell scripts
- bashdb: Bash debugger
- xtrace: Enhanced debugging output
Best Practices
- Use
set -euo pipefail
at the start of scripts - Implement proper error handling for all critical operations
- Use descriptive error messages that help identify the issue
- Log important events and errors to a file
- Clean up temporary files even when errors occur
- Test error conditions during development
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