Exit Codes and Debugging Scripts: A Beginner’s Guide to Linux
When you’re writing scripts in Linux, things don’t always go as planned. Sometimes your script runs perfectly, other times it fails mysteriously. This is where understanding exit codes becomes crucial for debugging and creating reliable scripts.
What Are Exit Codes?
Every command and script in Linux returns an exit code when it finishes running. Think of it as the script’s way of saying “I’m done, and here’s how it went.” Exit codes are numbers that tell you whether a command succeeded or failed, and if it failed, they can give you clues about what went wrong.
The most important exit codes to remember:
- 0: Success! Everything worked perfectly
- 1-255: Something went wrong (different numbers indicate different types of errors)
Checking Exit Codes
Let’s start with a simple example. Open your terminal and run a command:
The echo $?
command shows you the exit code of the last command that ran. If the ls
command worked, you’ll see 0
. Now try:
This time you’ll see a non-zero number (probably 2
), indicating the command failed.
Your First Script with Exit Codes
Let’s create a simple script to understand how this works. Create a file called check_file.sh
:
Make it executable and test it:
Common Exit Codes and Their Meanings
Different exit codes mean different things. Here are the most common ones:
- 0: Success
- 1: General error
- 2: Misuse of shell command
- 126: Command found but not executable
- 127: Command not found
- 128: Invalid exit argument
- 130: Script terminated by Ctrl+C
Building Better Scripts with Exit Codes
Now let’s create a more practical script that demonstrates proper error handling. This script will backup a directory:
|
|
Debugging Techniques
When your scripts don’t work as expected, here are powerful debugging techniques:
1. Use set -e
for Strict Error Handling
Add this at the beginning of your script to make it exit immediately when any command fails:
2. Use set -x
for Tracing
This shows you exactly what your script is doing:
3. Combine Both for Maximum Debugging
Creating a Robust Script Template
Here’s a template that incorporates good practices for error handling:
|
|
Testing Your Scripts
Always test your scripts with different scenarios:
|
|
Common Debugging Scenarios
Script Exits Unexpectedly
- Check if
set -e
is causing premature exits - Add
echo
statements to see where the script stops - Use
set -x
to trace execution
Variables Not Working
- Check for typos in variable names
- Ensure proper quoting:
"$variable"
instead of$variable
- Use
set -u
to catch undefined variables
Permission Issues
- Check file permissions with
ls -l
- Ensure your script is executable:
chmod +x script.sh
- Verify you have permission to read/write files the script accesses
Best Practices Summary
- Always use meaningful exit codes in your scripts
- Check the exit codes of important commands
- Use
set -e
to catch errors early - Use
set -x
when debugging - Provide helpful error messages
- Test your scripts with various inputs
- Use functions for error handling
- Log important actions and errors
Conclusion
Understanding exit codes is fundamental to writing reliable Linux scripts. They help you catch errors, debug problems, and create scripts that behave predictably. Start with simple scripts, add proper error handling, and gradually build more complex automation.
Remember: a good script doesn’t just work when everything goes right—it fails gracefully and tells you exactly what went wrong when things don’t go as planned. With exit codes and proper debugging techniques, you’ll be able to create robust scripts that you can trust in production environments.