Bash Signal Trap

Handling signals and interrupts in Bash scripts

🛡️ What is Signal Trap?

Signal trapping allows your Bash scripts to catch and handle system signals like Ctrl+C interrupts. It helps create robust scripts that clean up resources and exit gracefully when interrupted or terminated.


# Basic trap example
trap 'echo "Script interrupted!"' SIGINT

echo "Press Ctrl+C to test..."
sleep 10
                                    

Output (when Ctrl+C is pressed):

Press Ctrl+C to test...
Script interrupted!

Key Signal Trap Concepts

SIGINT

Interrupt signal (Ctrl+C)

trap 'echo "Caught SIGINT"' SIGINT
🚪

EXIT

Runs when script exits

trap 'echo "Cleaning up..."' EXIT
🛑

SIGTERM

Termination signal

trap 'cleanup; exit' SIGTERM

ERR

Catches command errors

trap 'echo "Error occurred"' ERR

🔹 Basic Trap Syntax

The trap command establishes signal handlers using syntax trap 'commands' SIGNALS to execute specified commands when signals are received. This enables graceful script termination, cleanup operations, and custom responses to system events. Basic traps catch common signals like EXIT, INT, and TERM to ensure proper resource management regardless of how the script ends.

#!/bin/bash

# Syntax: trap 'commands' SIGNAL

trap 'echo "Goodbye!"' EXIT
trap 'echo "Interrupted!"' SIGINT

echo "Script running..."
sleep 5
echo "Script completed"

Output:

Script running...
Script completed
Goodbye!

🔹 Cleanup with Trap

Use trap with EXIT signal to guarantee cleanup operations run whether the script completes normally or is interrupted. This ensures temporary files are removed, resources are released, and processes are terminated even when users press Ctrl+C or system events occur. Proper cleanup prevents resource leaks and maintains system cleanliness.

#!/bin/bash

# Create temp file
TEMP_FILE="/tmp/mytemp_$$"

# Cleanup function
cleanup() {
    echo "Cleaning up..."
    rm -f "$TEMP_FILE"
    echo "Temp file removed"
}

# Set trap
trap cleanup EXIT

# Create temp file
echo "Creating temp file..."
touch "$TEMP_FILE"
echo "Working with temp file..."
sleep 3

Output:

Creating temp file...
Working with temp file...
Cleaning up...
Temp file removed

🔹 Multiple Signal Handling

Handle multiple signals with single trap commands or different handlers for different signals using trap 'cleanup' EXIT INT TERM. This provides granular control over script behavior when receiving various termination requests. Different signals can trigger different responses, from graceful shutdown to immediate termination with specific cleanup procedures.

#!/bin/bash

# Handle multiple signals
trap 'echo "Caught INT or TERM"; exit 1' SIGINT SIGTERM

# Different handler for EXIT
trap 'echo "Script exiting..."' EXIT

echo "Running... (Press Ctrl+C to test)"
while true; do
    sleep 1
done

Output (when Ctrl+C pressed):

Running... (Press Ctrl+C to test)
Caught INT or TERM
Script exiting...

🔹 Ignoring Signals

Temporarily ignore signals using trap '' SIGNAL during critical operations that shouldn't be interrupted, then restore normal handling afterward. This prevents users from terminating important processes like data commits or file transfers. Signal ignoring should be used sparingly and restored promptly to maintain expected interactive behavior.

#!/bin/bash

# Ignore SIGINT (Ctrl+C)
trap '' SIGINT

echo "Critical operation (Ctrl+C disabled)..."
sleep 5

# Restore default behavior
trap - SIGINT

echo "Normal operation (Ctrl+C enabled)..."
sleep 5

Output:

Critical operation (Ctrl+C disabled)...
Normal operation (Ctrl+C enabled)...

🔹 Error Handling with Trap

The ERR trap automatically executes when any command fails (non-zero exit), enabling centralized error handling throughout your script. Combined with set -e, this creates robust error management that logs failures, performs cleanup, and can implement retry logic. ERR traps provide consistent response to errors regardless of where they occur in script execution.

#!/bin/bash

set -e  # Exit on error

# Error handler
error_handler() {
    echo "Error on line $1"
    echo "Command failed: $2"
    exit 1
}

trap 'error_handler $LINENO "$BASH_COMMAND"' ERR

echo "Starting script..."
ls /nonexistent/directory  # This will trigger error
echo "This won't execute"

Output:

Starting script...
Error on line 14
Command failed: ls /nonexistent/directory

🔹 Common Signal Numbers

Signals can be referenced by number or name, with common ones including 1 (SIGHUP), 2 (SIGINT), 9 (SIGKILL), and 15 (SIGTERM). Understanding signal purposes helps design appropriate handlers—SIGTERM for graceful shutdown, SIGKILL for immediate termination, SIGINT for user interrupts. Proper signal handling creates scripts that behave predictably in different termination scenarios.

  • SIGINT (2): Interrupt from keyboard (Ctrl+C)
  • SIGTERM (15): Termination signal (default kill)
  • SIGKILL (9): Force kill (cannot be trapped)
  • SIGHUP (1): Hangup detected
  • SIGQUIT (3): Quit from keyboard (Ctrl+\)
#!/bin/bash

# Using signal numbers
trap 'echo "Signal 2 caught"' 2
trap 'echo "Signal 15 caught"' 15

# Or use names (preferred)
trap 'echo "SIGINT caught"' SIGINT
trap 'echo "SIGTERM caught"' SIGTERM

🧠 Test Your Knowledge

Which signal is sent when you press Ctrl+C?