Exit Codes
Every command returns an exit code. 0 means success. Anything else means failure. Your scripts should do the same.
Checking Exit Codes
The special variable $? holds the last exit code:
Common Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Misuse of command |
| 126 | Permission denied |
| 127 | Command not found |
| 128+n | Killed by signal n |
| 130 | Ctrl+C (SIGINT) |
Using exit in Scripts
#!/bin/bash
if [[ ! -f "$1" ]]; then
echo "File not found: $1"
exit 1
fi
echo "Processing $1..."
# ... do work ...
exit 0 # explicit success
Exit 0 Is Optional
Scripts exit with the last command's exit code by default. Explicit exit 0 at the end is good practice for clarity.
Conditional Execution
Exit codes power && and ||:
&&runs next command only if previous succeeded (exit 0)||runs next command only if previous failed (exit non-0)
Exit on Error Pattern
#!/bin/bash
# Common pattern
command1 || { echo "command1 failed"; exit 1; }
command2 || { echo "command2 failed"; exit 1; }
command3 || { echo "command3 failed"; exit 1; }
Or use set -e:
#!/bin/bash
set -e # Exit on any error
command1 # Script exits if this fails
command2 # Only runs if command1 succeeded
command3
Check Specific Exit Codes
#!/bin/bash
grep "pattern" file.txt
exit_code=$?
case $exit_code in
0)
echo "Pattern found"
;;
1)
echo "Pattern not found"
;;
2)
echo "Error occurred"
;;
esac
Functions and Exit Codes
#!/bin/bash
check_disk_space() {
local usage=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if [[ $usage -gt 90 ]]; then
return 1 # Failure - disk nearly full
fi
return 0 # Success
}
if check_disk_space; then
echo "Disk space OK"
else
echo "Warning: Disk nearly full"
exit 1
fi
Practical Script Example
#!/bin/bash
# deploy.sh - Deployment with proper exit codes
set -e # Exit on error
log() { echo "[$(date '+%H:%M:%S')] $1"; }
# Validate environment
[[ -n "$DEPLOY_PATH" ]] || { echo "DEPLOY_PATH not set"; exit 1; }
[[ -d "$DEPLOY_PATH" ]] || { echo "Deploy path doesn't exist"; exit 1; }
log "Starting deployment..."
# Each command must succeed
log "Pulling latest code..."
git pull origin main
log "Installing dependencies..."
npm install
log "Building..."
npm run build
log "Restarting service..."
sudo systemctl restart myapp
log "Deployment complete!"
exit 0
Pipeline Exit Codes
By default, pipeline exit code is from the last command:
To check all commands in a pipeline:
#!/bin/bash
set -o pipefail # Pipeline fails if ANY command fails
false | true
echo $? # Now returns 1
What does exit code 0 mean?
Quick Reference
| Syntax | Purpose |
|---|---|
$? | Last exit code |
exit 0 | Exit successfully |
exit 1 | Exit with error |
set -e | Exit on any error |
set -o pipefail | Pipeline fails on any error |
cmd && next | Run next if cmd succeeds |
cmd || next | Run next if cmd fails |
Key Takeaways
- Exit code 0 = success, non-zero = failure
$?contains the last exit code- Always
exit 1(or other non-zero) on errors - Use
set -efor strict error handling &&chains successful commands||provides fallback on failure- Check exit codes when the reason for failure matters
Next: comprehensive error handling.