Bash scripting errors are frustrating because they often fail without clear error messages. If you have ever spent hours debugging a failing script only to realize the issue was a missing space, unquoted variable, or unexpected input, this guide is for you.
Unlike generic debugging lists, this guide provides a structured workflow for identifying, isolating, and fixing Bash script issues efficiently.
Need a quick-reference guide for Bash scripting?
๐ Get the Bash Cheat Sheet for $3.99
1. Step One: Enable Debug Mode (set -x
)
Common Problem:
The script executes, but the output is not what you expected, and there is no clear error.
Solution:
Run the script with set -x
to trace each command before execution.
bash -x myscript.sh
Or, enable debugging inside the script:
#!/bin/bash
set -x # Enable debug mode
echo "Starting script..."
mkdir /tmp/myfolder
set +x # Disable debug mode
Real-World Example:
A missing space in an if
statement can break your script silently:
if[$var="hello"]; then # Incorrect syntax
echo "Hello"
fi
Debugging with set -x
reveals:
myscript.sh: line 3: if[hello=hello]: command not found
Why it helps:
โ Shows exactly where the script fails
โ Reveals unexpected command substitutions
2. Stop Silent Failures with set -e
Common Problem:
A command fails, but the script keeps running, leading to unintended behavior.
Solution:
Use set -e
to stop execution immediately when an error occurs:
#!/bin/bash
set -e
cp myfile.txt /nonexistent-directory # Script exits immediately on failure
echo "This will never run."
For even better debugging, combine it with set -x
:
set -ex
Real-World Example:
Imagine a backup script that continues running even if rsync
fails:
#!/bin/bash
rsync -av /source /backup
echo "Backup completed"
If /source
does not exist, the script still prints "Backup completed", misleading the user.
Fixed with set -e
:
#!/bin/bash
set -e
rsync -av /source /backup
echo "Backup completed"
Now, if rsync
fails, the script stops immediately.
Why it helps:
โ Prevents silent script failures
โ Ensures errors do not cause unintended side effects
3. Catch Unexpected Failures with trap
Common Problem:
A script fails mid-execution, but you need cleanup actions before exiting.
Solution:
Use trap
to execute cleanup code when the script exits unexpectedly:
#!/bin/bash
trap 'echo "Error occurred at line $LINENO"; exit 1' ERR
mkdir /tmp/mydir
cp non_existent_file.txt /tmp/mydir # This will trigger the trap
echo "This won't execute."
Real-World Example:
You have a script that downloads and extracts a file:
#!/bin/bash
wget https://example.com/file.tar.gz
tar -xzf file.tar.gz
rm file.tar.gz
If wget
fails, the script still tries to extract and remove a non-existent file.
Fixed with trap
:
#!/bin/bash
trap 'echo "Download failed, cleanup skipped"; exit 1' ERR
wget https://example.com/file.tar.gz
tar -xzf file.tar.gz
rm file.tar.gz
Why it helps:
โ Captures exact error locations
โ Allows graceful script exits
4. Debug Variable Values (echo
vs printf
)
Common Problem:
Variables are not storing expected values.
Solution:
Print variable values to verify their content:
var="Hello World"
echo "Value of var: $var"
For debugging within a loop:
for i in {1..5}; do
echo "Current iteration: $i"
done
Real-World Example:
A script failing due to a whitespace issue:
name=" John "
if [ "$name" == "John" ]; then
echo "Match"
else
echo "No match"
fi
Fix it with:
name=$(echo "$name" | xargs)
Why it helps:
โ Identifies unexpected variable values
โ Helps with debugging loops and conditionals
5. Detect Syntax Errors with shellcheck
Common Problem:
The script runs but behaves unpredictably due to hidden syntax issues.
Solution:
Install and run shellcheck
to detect errors:
sudo apt install shellcheck # Debian/Ubuntu
shellcheck myscript.sh
It provides detailed explanations for errors, such as:
- Missing quotes around variables
- Incorrect command syntax
- Unused variables
Why it helps:
โ Prevents common scripting mistakes
โ Saves time compared to manual debugging
6. Log Debugging Output with tee
Common Problem:
A script runs on a server, but debugging messages disappear.
Solution:
Redirect output to a log file using tee
:
./myscript.sh | tee debug.log
For capturing stderr and stdout together:
./myscript.sh &> debug.log
Why it helps:
โ Allows post-run analysis of script output
โ Captures error messages for debugging
Final Thoughts: Debug Bash Like a Pro
Debugging Bash scripts is not about guessingโit is about applying the right techniques systematically.
Quick Debugging Checklist:
โ
Use set -x
to trace command execution
โ
Enable set -e
to stop on errors
โ
Use trap
to catch unexpected failures
โ
Validate variables and input before execution
โ
Run shellcheck
for instant syntax error detection
Want a Structured Bash Debugging Reference?
If you want a quick cheat guide with 100+ Bash commands, check out my Bash Cheat Book.
๐ Download the Bash Cheat Sheet for just $3.99
Whatโs Inside?
โ๏ธ Common Bash errors and fixes
โ๏ธ Debugging workflows for quick troubleshooting
โ๏ธ Formatted PDF for offline use
Master Bash debugging and eliminate frustrating script failures today.
Discussion: What was the hardest Bash bug you ever debugged?
Drop a comment below with your toughest debugging experience!
Top comments (0)