Friday, 13 March 2026

Trap signal in bash

Understanding trap in Bash Shell Scripting

In Bash scripting, the trap command allows you to execute a specific command or function when the shell receives a signal or when the script exits.

This is extremely useful for:

  • Cleaning up temporary files

  • Handling interrupts like Ctrl+C

  • Debugging scripts

  • Gracefully shutting down background jobs

You can view the list of signals supported by your system using:

trap -l

1. Running a Function When a Script Exits

Suppose you want to run a cleanup function at the end of a script execution.

The following script demonstrates that concept. Here we are using echo for demonstration purposes, but in real-world cases you might be removing temporary files, stopping services, or closing connections.

[root@oel01db Shell-Scripting]# cat 01-trap-on-exit.sh
#!/usr/bin/env bash

cleanup() {
echo cleanup function running
}

trap cleanup exit

echo script starting
echo ...
echo script done
[root@oel01db Shell-Scripting]#
[root@oel01db Shell-Scripting]# bash 01-trap-on-exit.sh
script starting
...
script done
cleanup function running
[root@oel01db Shell-Scripting]#

Why does the cleanup function run at the end?

You might notice that cleanup is declared before the echo statements, yet it runs after the script finishes.

This happens because of this line:

trap cleanup exit

This line does not execute the function immediately.
Instead, it tells Bash:

“Whenever this script exits, run the cleanup function.”

So when the script reaches the end of the file (which is an implicit exit), the trap is triggered and the cleanup function runs.


2. Trap Still Runs When Exiting with a Custom Exit Code

Now let's explicitly exit the script with a custom exit code and see what happens.

[root@oel01db Shell-Scripting]# cat 01-trap-on-exit-1.sh
#!/usr/bin/env bash

cleanup() {
echo cleanup function running
}

trap cleanup exit

echo script starting
echo ...
echo script done
exit 1
[root@oel01db Shell-Scripting]# bash 01-trap-on-exit-1.sh
script starting
...
script done
cleanup function running
[root@oel01db Shell-Scripting]# echo $?
1
[root@oel01db Shell-Scripting]#

Even though the script exits with exit 1, the cleanup function still runs.

Important detail

Inside the cleanup function, the exit code ($?) may temporarily change because commands like echo succeed and return 0.

However, Bash remembers the original exit code that triggered the trap and restores it after the trap finishes.

So the final exit code remains:

1

3. Overwriting the Exit Code Inside a Trap

A trap can override the exit code if it explicitly calls exit.

Example:

[root@oel01db Shell-Scripting]# cat 01-trap-on-exit-overwrite.sh
#!/usr/bin/env bash

cleanup() {
echo cleanup function running
exit 5
}

trap cleanup exit

echo "exiting with 1..."
exit 1
[root@oel01db Shell-Scripting]# bash 01-trap-on-exit-overwrite.sh
exiting with 1...
cleanup function running
[root@oel01db Shell-Scripting]#
[root@oel01db Shell-Scripting]# echo $?
5
[root@oel01db Shell-Scripting]#

Originally the script exited with:

exit 1

But because the cleanup function calls:

exit 5

the final exit code becomes 5.


4. Handling Ctrl+C (SIGINT)

When a user presses Ctrl+C, the shell sends the SIGINT signal.

We can intercept that signal using trap.

[root@oel01db Shell-Scripting]# cat o1-trap-on-ctrl+c.sh
#!/usr/bin/env bash

cleanup() {
echo
echo "Ctrl+C detected!"
echo "Cleaning up before exit..."
exit 1
}

trap cleanup SIGINT

echo "Script running. Press Ctrl+C to stop."

while true
do
echo "Working..."
sleep 2
done
[root@oel01db Shell-Scripting]# bash o1-trap-on-ctrl+c.sh
Script running. Press Ctrl+C to stop.
Working...
Working...
Working...
^C
Ctrl+C detected!
Cleaning up before exit...
[root@oel01db Shell-Scripting]# echo $?
1
[root@oel01db Shell-Scripting]#

Instead of abruptly terminating, the script runs the cleanup function first, ensuring that resources are properly released.


5. Real-World Example: Cleaning Temporary Files

This is a common production use case.

Imagine a script that creates a temporary file.
If the user presses Ctrl+C, the script must remove that file before exiting.

[root@oel01db Shell-Scripting]# cat 01-real-trap-on-ctrlc.sh
#!/usr/bin/env bash

tmpfile=$(mktemp)

cleanup() {
echo
echo "Interrupt received. Removing temp file..."
rm -f "$tmpfile"
exit 1
}

trap cleanup SIGINT

echo "Temp file created: $tmpfile"

while true
do
date >> "$tmpfile"
echo "Writing to temp file..."
sleep 2
done
[root@oel01db Shell-Scripting]#
[root@oel01db Shell-Scripting]# bash 01-real-trap-on-ctrlc.sh
Temp file created: /tmp/tmp.LTxRvxMmlu
Writing to temp file...
Writing to temp file...
^C
Interrupt received. Removing temp file...
[root@oel01db Shell-Scripting]#

Without trap, the temporary file would remain on disk.


6. Using trap for Debugging Scripts

Bash also supports a special trap called DEBUG.

The DEBUG trap runs before every command in the script.

[root@oel01db Shell-Scripting]# cat o1-trap-with-debug.sh
#!/usr/bin/env bash

my-func() {
echo "[DEBUG] running: $BASH_COMMAND"
}

trap my-func debug

echo script starting
echo ...
echo script done
exit 1
[root@oel01db Shell-Scripting]# bash o1-trap-with-debug.sh
[DEBUG] running: echo script starting
script starting
[DEBUG] running: echo ...
...
[DEBUG] running: echo script done
script done
[DEBUG] running: exit 1
[root@oel01db Shell-Scripting]#

How it works

Two key concepts are involved:

The DEBUG Trap

Unlike exit, which runs once at the end, the DEBUG trap runs before every command executed in the script.

The $BASH_COMMAND Variable

$BASH_COMMAND is a built-in Bash variable that contains the command about to be executed.

This allows you to implement simple script tracing and debugging mechanisms.


7. Common Signals Used with trap

Some commonly used signals include:

SignalMeaning
EXITRuns when the script exits
SIGINTTriggered by Ctrl+C
SIGTERMDefault termination signal
SIGHUPTerminal closed
SIGQUITQuit signal
DEBUGRuns before every command
ERRRuns when a command fails

Example:

trap cleanup EXIT SIGINT SIGTERM

This ensures cleanup runs for normal exit, Ctrl+C, or termination.


8. Best Practice: One Cleanup Trap for Everything

A very common pattern in production scripts is:

cleanup() {
rm -f "$tmpfile"
}

trap cleanup EXIT

Because the EXIT trap runs for almost all termination scenarios, this is usually enough to ensure proper cleanup.


Final Thoughts

The trap command is a powerful mechanism for building robust Bash scripts.

It allows your scripts to:

  • Handle interrupts safely

  • Clean up temporary files

  • Preserve correct exit codes

  • Implement debugging features

  • Prevent resource leaks

No comments:

Post a Comment

JFrog Artifactory - How to install

JFrog Artifactory OSS Installation Guide CentOS 9 + PostgreSQL 17 This guide provides a structured workflow to install JFrog Artifactory OSS...