The set -e
command is a fundamental shell option that causes a script to exit immediately if any command returns a non-zero exit status (indicating failure). This behavior is particularly useful for:
#!/bin/bash
set -e
rm critical_file.tmp
echo "This line won't execute if rm fails"
System administrators frequently employ set -e
in scenarios where:
- Configuration management scripts
- Deployment automation
- Critical system maintenance tasks
Example of safe usage pattern:
#!/bin/bash
set -e
backup_dir="/var/backups"
mkdir -p "$backup_dir"
tar -czf "$backup_dir/app_$(date +%F).tar.gz" /opt/app
While powerful, set -e
becomes dangerous when:
#!/bin/bash
set -e
grep "error" logfile || true # Without '|| true', script would exit
status_code=$(curl -s -o /dev/null -w "%{http_code}" example.com)
The second line demonstrates a common pitfall - command substitutions don't trigger set -e
, potentially hiding failures.
Consider this database backup script that went wrong:
#!/bin/bash
set -e
pg_dump -U user db > backup.sql
aws s3 cp backup.sql s3://bucket/ # If this fails, the script exits
rm backup.sql # File gets deleted even if upload failed
To mitigate risks while maintaining failure sensitivity:
#!/bin/bash
set -euo pipefail # Combines with other safety options
trap 'echo "Error at line $LINENO"; exit 1' ERR
temp_file=$(mktemp)
cleanup() { rm -f "$temp_file"; }
trap cleanup EXIT
# Main script logic here
For complex error handling needs:
#!/bin/bash
error_handler() {
echo "Error occurred in $1" >&2
exit 1
}
command1 || error_handler "command1"
command2 || error_handler "command2"
Certain scenarios warrant disabling this behavior:
#!/bin/bash
# Section where failures are expected
set +e
count=$(grep -c "pattern" file)
set -e
if (( count > 0 )); then
handle_matches
fi
The set -e
command is a shell option that causes a script to exit immediately if any command returns a non-zero exit status (indicating failure). This behavior is often referred to as "errexit" or "exit on error."
#!/bin/bash
set -e
nonexistent_command # This will cause the script to exit
echo "This line won't be executed"
Many programmers use set -e
to make their scripts more robust by:
- Preventing silent failures
- Ensuring early termination when something goes wrong
- Making error handling more predictable
Despite its usefulness, set -e
has several surprising behaviors that can make scripts behave unexpectedly:
#!/bin/bash
set -e
false | true # The pipe succeeds despite 'false' failing
echo "This line executes because the pipeline succeeds"
Other problematic cases include:
- Commands in conditionals (if, while, until)
- Functions that check return codes
- Commands in command substitution $(...)
Consider this common pattern that fails with set -e
:
#!/bin/bash
set -e
if ! grep "pattern" file.txt; then
echo "Pattern not found" # This might never execute
fi
Instead of relying solely on set -e
, consider:
#!/bin/bash
set -eo pipefail # More strict version
# Or explicit error checking:
command || { echo "Error occurred"; exit 1; }
set -e
can be useful in:
- Simple, linear scripts
- Cases where any failure should abort the entire operation
- Combination with
trap
for cleanup
#!/bin/bash
set -e
trap 'cleanup_function' EXIT
# Rest of script...