Trap Command to Catch Errors in Bash

In Bash scripting, errors can occur unexpectedly, leading to incomplete processes or leaving temporary files and resources behind. To handle such scenarios effectively, Bash provides a powerful mechanism called trap.

The trap command allows you to specify commands or functions to execute when your script receives a specific signal, such as an error or termination request. This helps in managing cleanups, handling errors gracefully, and ensuring that your scripts do not leave behind unnecessary artifacts.

In this tutorial, we shall go through the syntax of trap command, usage of trap command with examples, how to trap multiple signals, when to use trap command, and the best practices whiles using trap command.

This guide is part of Error Handling in Bash Shell Scripting.


Syntax

The basic syntax of the trap command in Bash is as follows:

</>
Copy
trap 'commands' signals

In this syntax:

  • commands: One or more commands or functions to execute when the specified signals are received.
  • signals: A list of signals (such as SIGINT, SIGTERM, or EXIT) that the trap will respond to.

For example, you can use trap to execute a cleanup function when the script exits, regardless of the reason:

</>
Copy
trap 'cleanup_function' EXIT

Examples of Using trap in Bash

Let’s go through several examples to understand how trap can be used effectively in Bash scripts.


1. Using trap for Cleanup on Exit

In this example, we will use trap to ensure that temporary files created by the script are deleted when the script exits, either normally or due to an error.

example.sh

</>
Copy
#!/bin/bash

# Function to clean up temporary files
cleanup() {
    echo "Cleaning up temporary files..."
    rm -f /tmp/tempfile.txt
}

# Set a trap for the EXIT signal
trap cleanup EXIT

# Create a temporary file
echo "Creating a temporary file..."
touch /tmp/tempfile.txt

# Simulate some processing
echo "Processing data..."
sleep 2

# Exit the script
echo "Exiting script."
exit 0

Output

Bash - Using trap for Cleanup on Exit

In this script, the trap command catches the EXIT signal and calls the cleanup function. This ensures that the temporary file is deleted even if the script exits unexpectedly.


2. Handling Interrupt Signals (SIGINT)

In this example, we use trap to handle the SIGINT signal, which is sent when the user presses Ctrl + C. Instead of abruptly terminating the script, we can display a custom message and perform any necessary cleanup.

example.sh

</>
Copy
#!/bin/bash

# Function to handle Ctrl + C (SIGINT)
handle_interrupt() {
    echo "Script interrupted by user. Exiting gracefully..."
    exit 1
}

# Set a trap for SIGINT
trap handle_interrupt SIGINT

# Simulate a long-running process
echo "Running a long process. Press Ctrl + C to interrupt."
for i in {1..5}
do
    echo "Processing step $i..."
    sleep 2
done

echo "Process completed successfully."

Output

Bash trap command - Handling Interrupt Signals (SIGINT)

Here, when the user presses Ctrl + C, the SIGINT signal is sent to the script. The trap command catches this signal and calls the handle_interrupt function, allowing the script to exit gracefully.


3. Using trap for Error Handling with ERR Signal

The ERR signal in Bash is triggered when a command fails (returns a non-zero exit code). By using trap with ERR, you can create a handler function that runs whenever an error occurs.

example.sh

</>
Copy
#!/bin/bash

# Function to handle errors
error_handler() {
    echo "An error occurred. Exiting script."
    exit 1
}

# Set a trap for the ERR signal
trap error_handler ERR

# Command that will fail
echo "Attempting to copy a nonexistent file..."
cp /nonexistent/file /tmp/

# This line will not be executed if an error occurs
echo "This message will not appear."

Output

Bash trap command for Error Handling with ERR Signal

In this script, the trap command catches the ERR signal and calls the error_handler function whenever an error is encountered, preventing the script from continuing execution.


4. Trapping Multiple Signals in Bash

You can use the trap command to handle multiple signals with a single handler function. This is particularly useful when you want to perform cleanup or execute specific commands regardless of how the script is terminated (e.g., via Ctrl + C, kill command, or normal exit).

example.sh

</>
Copy
#!/bin/bash

# Define a function to handle cleanup
cleanup() {
    echo "Caught a signal! Cleaning up and exiting..."
    # Remove temporary files or perform other cleanup tasks
    rm -f /tmp/tempfile.txt
    exit 0
}

# Set traps for multiple signals: SIGINT (Ctrl + C), SIGTERM (termination), and EXIT
trap cleanup SIGINT SIGTERM EXIT

# Create a temporary file
echo "Creating a temporary file..."
touch /tmp/tempfile.txt

# Simulate a long-running process
echo "Running a long process. Press Ctrl + C to interrupt or terminate the script."
sleep 10

# If the script completes normally
echo "Process completed successfully. Exiting."
exit 0

Output

Trapping Multiple Signals in Bash

In this example:

  • SIGINT: Triggered when the user presses Ctrl + C.
  • SIGTERM: Sent when the script is terminated using the kill command.
  • EXIT: Triggered when the script exits, either normally or due to an error.

By trapping multiple signals, the cleanup function is called in all these scenarios, ensuring that temporary files are deleted and the script exits gracefully.

This approach helps prevent issues like leftover temporary files or incomplete processes, making your script more robust and user-friendly.

When to Use trap command in Bash Scripts

The trap command is particularly useful in the following scenarios:

  • **Cleanup on Exit**: Use trap with the EXIT signal to ensure temporary files and resources are cleaned up.
  • **Graceful Shutdown**: Handle interrupt signals like SIGINT (Ctrl + C) to provide a graceful exit and perform necessary cleanup.
  • **Error Handling**: Use trap with the ERR signal to catch errors and execute error-handling functions.
  • **Debugging**: Implement trap with the DEBUG signal to trace script execution for debugging purposes.

Best Practices for Using trap

  • Always define cleanup functions for EXIT traps to avoid leaving temporary files behind.
  • Use meaningful and informative error messages in error handlers for better debugging.
  • Test your traps with various signals to ensure they handle interruptions correctly.
  • Combine set -e with trap ERR for comprehensive error handling in scripts.

By using trap effectively, you can make your Bash scripts more resilient, reliable, and easier to maintain.