Linux Trap Command: Handle Script Interruptions

The Linux trap command enables shell scripts to intercept and handle system signals, allowing processes to shut down gracefully instead of terminating abruptly. By capturing signals such as user interrupts or termination requests, scripts can execute predefined cleanup routines, ensuring that temporary files are deleted, system resources are freed, and child processes are stopped before the shell exits.

Understanding Signals and the Trap Command

In a Linux environment, the operating system and users communicate with running processes by sending asynchronous notifications called signals. When a signal is received, the default behavior for most scripts is immediate termination, which often leaves behind temporary files, locked resources, or orphaned background tasks.

The trap command is a built-in feature of POSIX-compliant shells (such as Bash, Dash, and Zsh) that overrides these default termination behaviors. It allows developers to bind specific shell commands or custom functions to particular signals.

Common Signals Handled by Trap

Syntax and Basic Usage

The basic syntax for the trap command associates an action with one or more signal names or numbers:

trap 'action' SIGNAL_LIST

Implementing a Cleanup Routine

The most common use case for trap is cleaning up temporary directories and resetting configurations before a script terminates.

#!/bin/bash

# Create a temporary working directory
TEMP_DIR=$(mktemp -d /tmp/myscript.XXXXXX)
echo "Working directory created: $TEMP_DIR"

# Define the cleanup function
cleanup() {
    echo "Signal received or script exiting. Cleaning up..."
    rm -rf "$TEMP_DIR"
    echo "Cleanup complete."
}

# Catch SIGINT, SIGTERM, and the EXIT pseudo-signal
trap cleanup SIGINT SIGTERM EXIT

# Simulate long-running work
for i in {1..10}; do
    echo "Processing step $i..."
    sleep 2
done

In this script, whether the user presses Ctrl+C (SIGINT), a system administrator runs kill <PID> (SIGTERM), or the loop finishes naturally (EXIT), the cleanup function runs automatically, removing the temporary directory.

Ignoring and Resetting Signals

The trap command also provides mechanisms to deliberately ignore signals or revert them back to system defaults.

Ignoring Signals

To make a critical section of code immune to user cancellation, assign an empty string as the action:

# Ignore interrupt signals during a critical task
trap '' SIGINT SIGTERM

echo "Executing critical task, cannot be interrupted..."
# Critical database update or file write occurs here
sleep 5

# Reset back to default behavior
trap - SIGINT SIGTERM

Resetting to Default Behavior

Passing a hyphen (-) as the action resets the specified signals to their default operating system handlers:

trap - SIGINT

Best Practices for Using Trap

  1. Keep Handlers Non-Blocking: The actions triggered by trap should execute quickly to avoid hanging during system shutdowns.
  2. Explicit Exit Codes: When trapping SIGINT or SIGTERM manually without the EXIT pseudo-signal, explicitly exit with an appropriate status code (e.g., exit 130 for SIGINT) so upstream calling processes know the script did not complete successfully.
  3. Clean Up Background Jobs: If a script spawns child processes in the background using &, the cleanup function can terminate them using kill $(jobs -p) to prevent orphan processes.