๐ Extended Traps and Signals
Signals are asynchronous notifications sent to processes. Traps let you intercept and handle them gracefully.
๐งญ Common Signals
| Signal |
Number |
Description |
Default Action |
| SIGINT |
2 |
Ctrl+C โ Interrupt |
Terminate |
| SIGTERM |
15 |
Termination request |
Terminate |
| SIGKILL |
9 |
Force kill (cannot trap) |
Terminate |
| SIGHUP |
1 |
Hangup (terminal closed) |
Terminate |
| SIGSTOP |
19 |
Stop process (cannot trap) |
Stop |
| SIGCONT |
18 |
Continue stopped process |
Continue |
| SIGUSR1 |
10 |
User-defined 1 |
Terminate |
| SIGUSR2 |
12 |
User-defined 2 |
Terminate |
๐งช Basic Trap Usage
Catch Ctrl+C
| trap 'echo "Interrupted!"; exit 1' INT
while true; do
sleep 1
echo "Running..."
done
|
Press Ctrl+C โ prints "Interrupted!" and exits cleanly.
Multiple Signals
| cleanup() {
echo "Cleaning up..."
rm -f /tmp/myapp.lock
exit 0
}
trap cleanup INT TERM EXIT
|
This catches:
- Ctrl+C (INT)
- kill command (TERM)
- Any exit (EXIT)
๐ง Ignoring Signals
Prevent accidental termination:
| trap '' INT # Ignore Ctrl+C
trap '' TERM # Ignore termination requests
|
Useful for critical sections:
| critical_section() {
trap '' INT TERM # Protect during critical work
# Sensitive operations
write_to_database
trap - INT TERM # Restore default handling
}
|
๐งช Resetting Traps
Restore default behavior:
| trap - INT # Reset INT to default
trap - # Reset all traps
|
Check current trap:
| trap -p INT # Shows what INT trap is set to
|
๐ง Practical Use Cases
Graceful Shutdown
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | shutdown_requested=false
graceful_shutdown() {
echo "Shutdown signal received..."
shutdown_requested=true
}
trap graceful_shutdown TERM INT
while [ "$shutdown_requested" = false ]; do
process_next_job
sleep 1
done
echo "Performing final cleanup..."
cleanup_resources
exit 0
|
Temporary Signal Handlers
| pause_processing() {
trap 'echo "Paused. Resume with fg."' TSTP
kill -STOP $$ # Pause this process
}
resume_processing() {
trap - TSTP
kill -CONT $$ # Resume this process
}
|
๐งช Sending Signals to Processes
| # Find process by name
pid=$(pgrep nginx | head -1)
# Send signals
kill -TERM $pid # Graceful termination
kill -KILL $pid # Force kill (last resort)
kill -HUP $pid # Reload config (common for daemons)
kill -USR1 $pid # Custom action (e.g., rotate logs)
|
Check if process responded:
| kill -0 $pid 2>/dev/null && echo "Process exists" || echo "Process gone"
|
๐ง Signal Handling in Functions
Traps are global โ they affect the entire shell:
| setup_trap() {
trap 'cleanup' EXIT
}
cleanup() {
echo "Cleaning up from $FUNCNAME"
}
setup_trap
# cleanup will run when script exits, even from nested functions
|
๐งช Debugging Signal Issues
Trace signal delivery:
| trap 'echo "Received signal: $1"' DEBUG
|
Or use strace:
| strace -e trace=signal ./myscript.sh
|
๐งพ Summary
- Trap
INT, TERM, EXIT for graceful shutdowns.
- Use
trap '' to protect critical sections.
SIGKILL and SIGSTOP cannot be trapped.
- Send custom signals with
kill -USR1, etc.
- Always clean up resources in trap handlers.
- Test signal handling under load.
๐ Continue to: Subprocesses and Subshells