Debugging Scripts
When scripts don't work as expected, you need debugging tools. Learn techniques to find and fix bugs in bash scripts.
Debug Mode with -x
The most powerful debugging tool:
#!/bin/bash
set -x # Enable debug mode
NAME="Alice"
echo "Hello, $NAME"
# Output shows each command before execution:
# + NAME=Alice
# + echo 'Hello, Alice'
# Hello, Alice
Run with debug flag:
bash -x script.sh
Selective Debugging
Enable only for sections:
#!/bin/bash
echo "Normal output"
set -x # Enable debug
problematic_function
set +x # Disable debug
echo "Back to normal"
Verbose Mode with -v
Show commands as read (before expansion):
#!/bin/bash
set -v
NAME="Alice"
echo "Hello, $NAME"
# Shows: echo "Hello, $NAME"
# Then: Hello, Alice
Exercise: Debug a Command
Use debug mode:
Print Debugging
Classic debugging with echo:
#!/bin/bash
debug() {
[ "$DEBUG" = "1" ] && echo "DEBUG: $*" >&2
}
debug "Starting script"
debug "Variable X = $X"
debug "Entering loop"
# Run with: DEBUG=1 ./script.sh
Using PS4 for Debug Prefix
Customize debug output format:
#!/bin/bash
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
set -x
my_function() {
echo "In function"
}
my_function
# Shows: +(script.sh:8): my_function(): echo 'In function'
Syntax Checking with -n
Check syntax without executing:
bash -n script.sh
# No output = syntax OK
# Shows errors if syntax problems
#!/bin/bash
# Missing quote - syntax error
echo "Hello
# bash -n would catch this
Common Bugs and Solutions
Unquoted Variables
# Bug: word splitting
FILE="my file.txt"
cat $FILE # Tries to cat "my" and "file.txt"
# Fix: quote variables
cat "$FILE"
Missing Spaces in Tests
# Bug: no spaces
if [$X -eq 5]; then # Error!
# Fix: spaces required
if [ $X -eq 5 ]; then
Assignment vs Comparison
# Bug: using = in arithmetic
if [ $X=5 ]; then # Always true!
# Fix: spaces around =, or use -eq
if [ "$X" = "5" ]; then
if [ $X -eq 5 ]; then
Exercise: Find the Bug
Debug a simple script:
Using trap for Debug
Track execution:
#!/bin/bash
trap 'echo "DEBUG: Line $LINENO: $BASH_COMMAND"' DEBUG
X=5
Y=$((X * 2))
echo "Result: $Y"
Checking Variable States
#!/bin/bash
# Show all variables
set
# Show specific variable info
declare -p MY_VAR
# Check if set
if [ -v MY_VAR ]; then
echo "MY_VAR is set to: $MY_VAR"
else
echo "MY_VAR is not set"
fi
Logging for Debugging
#!/bin/bash
LOG_FILE="/tmp/script_debug.log"
log() {
local level="$1"
shift
echo "[$(date '+%H:%M:%S')] [$level] $*" | tee -a "$LOG_FILE" >&2
}
log INFO "Script started"
log DEBUG "Processing file: $FILE"
log ERROR "Failed to open file"
Interactive Debugging
Step through with read:
#!/bin/bash
step() {
echo "Press Enter to continue..."
read
}
echo "Step 1: Setting up"
step
echo "Step 2: Processing"
step
echo "Step 3: Cleanup"
Debugging Checklist
When scripts fail, check:
- Syntax:
bash -n script.sh - Execution trace:
bash -x script.sh - Variable values: Add echo statements
- Exit codes: Check
$?after commands - Quoting: Are variables properly quoted?
- Spaces: Are tests formatted correctly?
- Paths: Are file paths correct?
- Permissions: Can the script access needed files?
Debugging Tools Summary
| Tool | Purpose |
|---|---|
set -x | Show commands as executed |
set -v | Show commands as read |
set -e | Exit on error |
bash -n | Syntax check only |
trap DEBUG | Run command before each line |
declare -p | Show variable details |
PS4 | Customize debug prefix |
Key Takeaways
set -xis your primary debugging tool- Use
bash -nto check syntax before running - Customize debug output with
PS4 - Add
debugfunctions for controlled output - Common bugs: missing quotes, spaces, wrong operators
- Check exit codes after important commands
- Use traps to track execution flow
- Log to files for complex debugging

