Innovate | Connect | Transform
ContactService statusUSD $

GICT knowledge base

How to Use the trap Command in Bash

Published

LinuxLinux and CommandsLinux Scripting

Ever written a Bash script that’s supposed to run for a while say, copying files, processing data, or maybe spinning through a long loop and found yourself wondering what happens if you hit Ctrl+C or if the system randomly kills your script? If you haven’t thought about it yet, trust me: you will eventually! The first time you find your /tmp directory clogged with leftover temp files, or realize your script left a lockfile behind and now nothing else can run, you’ll start wishing there was a way to clean up after yourself, no matter how your script ends.

That’s where the trap command comes in. It’s one of those tools that feels almost invisible until you need it. Once you get the hang of it, you’ll wonder how you ever wrote scripts without it. So let’s break it down, step by step, in plain language, with plenty of examples and a few stories from the trenches.

What is trap and Why Should You Care?

In Bash (and most POSIX shells), the trap command lets you catch signals things like someone hitting Ctrl+C, or the script finishing, or even an unexpected error and then do something before your script exits. The “something” can be as simple as cleaning up temporary files, removing a lock file, or just printing a friendly goodbye message.

Signals are kind of like the ways your computer and your scripts communicate “urgent news.” For example, when you hit Ctrl+C, the shell sends a SIGINT (interrupt) to your script. If another process calls kill on your script, it might send SIGTERM. The trap command gives you a chance to intercept those signals, do some housekeeping, and then exit gracefully.

Why use it?

Let’s be honest: most scripts, especially the quick-and-dirty ones, don’t bother with trap at all. But if your script is doing anything with temporary files, lockfiles, network connections, background processes, or really anything that might leave a mess if it’s interrupted, trap is your best friend.

Getting Started: The Basics of trap

Here’s the simplest version:

trap 'echo "Goodbye!"' EXIT

With that line in your script, “Goodbye!” will print out every time your script exits no matter if it finished normally, crashed, or was interrupted.

Let’s see a more practical example:

#!/bin/bash
TEMPFILE=$(mktemp)
trap 'rm -f "$TEMPFILE"; echo "Cleaned up."' EXIT
echo "Working with $TEMPFILE..."
sleep 10
echo "Done!"

Try running that, then hit Ctrl+C during the sleep. You’ll see “Cleaned up.” And if you check /tmp, your temp file will be gone. Magic!

Catching Specific Signals

While EXIT is a sort of “catch-all,” you can also trap individual signals. The most common are:

  • SIGINT (2): Sent when you hit Ctrl+C.
  • SIGTERM (15): The default signal when you use the kill command.
  • SIGHUP (1): Sent when a terminal closes or a process is disconnected.

Here’s how you might handle just Ctrl+C:

trap 'echo "You pressed Ctrl+C! Exiting..."; exit 130' SIGINT
while true; do
    echo "Working... (press Ctrl+C to quit)"
    sleep 2
done

When you press Ctrl+C, you’ll get a custom message and the script will exit with exit code 130 (which is a convention for an interrupted process).

Real-World Story: The Forgotten Lockfile

I’ll never forget the time I wrote a deployment script that used a lockfile to make sure only one copy ran at a time. It worked until someone killed the script with Ctrl+C. The lockfile was still there, so the next run refused to start, even though nothing was actually running. We scratched our heads for a while until someone noticed the stale lock.

After that, I always used:

trap 'rm -f /tmp/my.lock' EXIT

No more leftover locks.

Advanced Usage: Custom Cleanup Functions

You don’t have to put all your cleanup code inline. In fact, it’s often neater to write a function:

cleanup() {
    echo "Doing cleanup..."
    rm -f "$TEMPFILE"
    # Any other cleanup steps here
}
trap cleanup EXIT

If your script is long or complicated, this makes it much easier to manage. Plus, you can call cleanup manually if you need to.

Multiple Signals, One Trap

You can list several signals in one go:

trap 'cleanup' SIGINT SIGTERM SIGHUP

Now the same cleanup code runs if you hit Ctrl+C, or if the process is killed, or if the terminal closes.

Ignoring Signals

Sometimes, you might want your script to ignore interrupts entirely. Maybe you don’t want the user to be able to kill it with Ctrl+C. (Use this with care! It can be frustrating if overused.)

trap '' SIGINT

Now, Ctrl+C does nothing. To restore default behavior:

trap - SIGINT

Unsetting a Trap

If you need to remove a trap during your script (maybe after your critical section is done), just use:

trap - EXIT

After that, the EXIT trap is no longer active.

Example: Cleaning Up in a Temporary Directory

Suppose your script makes a temp directory for its work:

WORKDIR=$(mktemp -d)
trap 'rm -rf "$WORKDIR"' EXIT
cd "$WORKDIR" 
# Do stuff here

If the script is interrupted at any point, the temp directory is deleted. No more disk clutter!

Trap and Error Handling

You can combine trap with error handling for robust scripts. For example, you might want to clean up if anything fails, not just on normal exit:

set -e  # Exit on any error
trap 'cleanup' EXIT
cleanup() {
    local code=$?
    echo "Script exited with code $code"
    rm -rf "$WORKDIR"
}

Now, no matter how the script ends, cleanup happens and you know the exit code too.

Pitfalls and Tips

  • Quote your trap code: Always use single quotes around your trap commands. Otherwise, Bash might expand variables too early.
    trap 'rm -f "$TEMPFILE"' EXIT
  • Set the trap early: Place your trap commands as close to the top as possible, before you create files or start critical actions.
  • Traps in subshells: Traps don’t automatically propagate into subshells. If you run code in ( … ), set the trap inside the subshell if needed.
  • Test your traps: Try interrupting your script in different ways (Ctrl+C, kill, normal exit) to make sure your trap works as you expect.

FAQ

Can I trap multiple signals at once?
Yes. Just list them: trap 'cleanup' SIGINT SIGTERM

Will trap work if the system is powered off?
No. If the system crashes or loses power, the script can’t run cleanup code.

What signals can I trap?
Most, but not all. You can’t trap SIGKILL (9) or SIGSTOP (19).

Can I see which traps are active?
Run trap -p to list current traps.

Conclusion

The trap command is one of those little Bash tricks that transforms your scripts from fragile one-offs into professional, reliable tools. With a simple line or two, you can handle interruptions gracefully, clean up after yourself, and avoid the classic problems that plague so many shell scripts.

Whether you’re automating a build, processing files, or writing internal tools, think about what could go wrong and use trap to make sure your scripts behave well, even when life (or the user) throws a wrench in the works.

If you haven’t tried using trap yet, give it a spin in your next script. You’ll quickly see why it’s a must-have for anyone serious about shell scripting.

Related guides

Account services are unavailable until the production backend is configured.