🎁 New User? Get 20% off your first purchase with code NEWUSER20 Register Now →
Menu

Categories

trap Command

Intermediate Shell Scripting man(1)

Handle signals and cleanup in shell scripts

📅 Updated: Mar 16, 2026
SYNTAX
trap COMMAND SIGNAL [SIGNAL...]

What Does trap Do?

The trap command sets up signal handlers in shell scripts — executing specified commands when the script receives a signal (like SIGINT from Ctrl+C), exits (EXIT), or encounters an error (ERR). It is one of the most important commands for writing robust, production-quality shell scripts.

The most common use of trap is cleanup on exit — removing temporary files, releasing locks, restoring terminal settings, or sending notifications when a script finishes. Without trap, scripts that are interrupted (Ctrl+C, kill, error) leave behind temporary files, locked resources, and incomplete state.

trap handles several types of events: EXIT (any script exit, normal or abnormal), SIGINT (Ctrl+C), SIGTERM (kill command), ERR (any command returning non-zero with set -e), SIGHUP (terminal hangup), and RETURN (function/source return). You can set multiple traps for different signals.

Understanding trap is essential for system administration scripts, deployment scripts, backup scripts, and any script that creates temporary resources or needs guaranteed cleanup.

Options & Flags

OptionDescriptionExample
trap COMMAND EXIT Execute command when script exits (any reason) trap "rm -f /tmp/lockfile" EXIT
trap COMMAND SIGINT Handle Ctrl+C interrupt trap "echo Interrupted; exit 1" SIGINT
trap COMMAND SIGTERM Handle kill/terminate signal trap "cleanup; exit" SIGTERM
trap COMMAND ERR Execute on any command error (with set -e) trap 'echo "Error at line $LINENO"' ERR
trap '' SIGNAL Ignore a signal (empty string handler) trap '' SIGINT
trap - SIGNAL Reset signal to default handler trap - SIGINT
trap -p Print current trap settings trap -p

Practical Examples

#1 Cleanup temporary files on exit

Remove temp file when script exits — whether normally, by Ctrl+C, or on error. The most common and important trap pattern.
$ #!/bin/bash\ntmpfile=$(mktemp)\ntrap "rm -f $tmpfile" EXIT\n# script work here...\necho "data" > "$tmpfile"

#2 Handle Ctrl+C gracefully

Catch Ctrl+C, run cleanup function, then exit with code 130 (128+SIGINT=2).
$ #!/bin/bash\ntrap "echo; echo 'Interrupted. Cleaning up...'; cleanup; exit 130" SIGINT\nfunction cleanup() { rm -f /tmp/lockfile; }\n# long-running work...

#3 Error handling with line number

On any error, print the line number and failed command. Combined with set -e for fail-fast behavior.
$ #!/bin/bash\nset -euo pipefail\ntrap 'echo "ERROR at line $LINENO: command \\"$BASH_COMMAND\\" failed with exit code $?"' ERR\n# script continues...

#4 Release lock file on exit

Create a lock file and ensure it is always removed, even if the script crashes.
$ #!/bin/bash\nLOCKFILE="/var/run/myscript.lock"\nif [ -f "$LOCKFILE" ]; then echo "Already running"; exit 1; fi\ntouch "$LOCKFILE"\ntrap "rm -f $LOCKFILE" EXIT\n# script work...

#5 Multiple signal handlers

Set different handlers for different signals. EXIT trap runs AFTER SIGINT/SIGTERM handlers.
$ #!/bin/bash\ntrap "echo Normal exit" EXIT\ntrap "echo Ctrl+C pressed; exit 130" SIGINT\ntrap "echo Terminated; exit 143" SIGTERM

#6 Cleanup function pattern

Define a cleanup function that handles multiple resources. Call it from trap for any exit scenario.
$ #!/bin/bash\ncleanup() {\n echo "Cleaning up..."\n [ -f "$tmpfile" ] && rm -f "$tmpfile"\n [ -f "$lockfile" ] && rm -f "$lockfile"\n docker rm -f test-container 2>/dev/null\n}\ntrap cleanup EXIT\ntmpfile=$(mktemp)\nlockfile="/tmp/deploy.lock"

#7 Ignore signals during critical section

Temporarily make script un-interruptible during critical operations like database writes.
$ #!/bin/bash trap '' SIGINT SIGTERM # ignore during critical section # critical database update here... trap - SIGINT SIGTERM # restore default handlers

Tips & Best Practices

Always use trap EXIT for cleanup: trap EXIT runs on ANY exit — normal, error, Ctrl+C, or kill. It is the most reliable way to ensure cleanup. Use it for temp files, lock files, and resource release.
EXIT trap runs after signal traps: If you have both SIGINT and EXIT traps, on Ctrl+C: SIGINT handler runs first, then EXIT handler. Avoid duplicating cleanup in both handlers.
SIGKILL cannot be trapped: kill -9 (SIGKILL) cannot be trapped or caught by any process. Avoid kill -9 in scripts — use kill (SIGTERM) first to allow clean shutdown.
Use with set -e: Combine trap ERR with set -e (exit on error) for robust error handling: set -euo pipefail; trap 'echo "Error line $LINENO"' ERR

Frequently Asked Questions

How do I clean up temporary files when a script exits?
Use: trap "rm -f $tmpfile" EXIT — this runs the rm command no matter how the script exits (normal, error, Ctrl+C, kill).
How do I handle Ctrl+C in a bash script?
Use: trap "echo Interrupted; cleanup; exit 130" SIGINT. The exit code 130 is the convention for SIGINT (128 + signal number 2).
Can I trap SIGKILL (kill -9)?
No. SIGKILL and SIGSTOP cannot be caught, blocked, or handled. Always use SIGTERM (kill) first to allow scripts to clean up. SIGKILL should be a last resort.
What is the difference between trap EXIT and trap SIGTERM?
EXIT runs on ANY script exit (normal, error, signal). SIGTERM only runs when the script receives a terminate signal. EXIT is more comprehensive — use it for cleanup.

Master Linux with Professional eBooks

Curated IT eBooks covering Linux, DevOps, Cloud, and more

Browse Books →