Work the Shell - Dealing with Signals

By handling signals in your bash scripts, you can provide features that are otherwise difficult, such as telling your script to reread its configuration file after it's already been started.

right before the section where I don't want the Ctrl-Z to work, it'll ignore that first Ctrl-Z, then reset the signal handler and work as expected the second time you press that key.

More useful is to ignore all Ctrl-Z stop signals until you're ready to deal with them, and that's quite easily done with the minimalist:

trap : TSTP  # ignore Ctrl-Z requests

And, then when you're ready to receive them again:

trap - TSTP  # allow Ctrl-Z requests

Experimentation will show that there are some weird terminal buffering issues associated with SIGTSTP, however, so don't be surprised if you have a signal handler that has output. In this particular instance, it won't show up until the script quits.

Reading a Configuration File

Let's look at a more practical example. Say you have an admin script that is always supposed to be running as a dæmon, but occasionally you want to tweak its configuration file and have it reread its setup (a lot faster than killing and restarting it).

Further, let's use SIGUSR1 for this task, as that is its intended use, so we're using the kernel's signal handling subsystem in the manner it was intended.

Reading a configuration file might be something as simple as:

. $config

(Recall that using . means that any variables set in the secondary file affect the current shell, not a subshell. The source command does the same thing as the . command.)

Here's our script to experiment with this feature:


  echo "(SIGUSR1: re-reading config file)"
  . $config

trap sigusr1 USR1       # catch -USR1 signal

echo "Daemon started. Assigned PID is $$"

. $config               # read it first time

while /usr/bin/true; do
  echo "Target number = $number"
  sleep 5

trap - USR1             # reset to be elegant

exit 0

We'll start with the configuration file containing number=5, then after 10–15 seconds, change it to number=1. Until we send the actual USR1 signal, however, the script just plugs along without a clue that it has changed:

$ ./
Daemon started. Assigned PID is 25843
Target number = 5
Target number = 5
Target number = 5

Meanwhile, in another window, I've already edited the file, so I type in this command:

$ kill -USR1 25843

And, here's what happens in the main script window:

(SIGUSR1: re-reading config file)
Target number = 1
Target number = 1

Cool, eh?

I hope this exploration of signal handling in shell scripts is useful. I actually learned quite a bit about advanced handling as I researched the code here. I'm still a bit stymied about how to reset the output stream after catching a SIGTSTP, but I bet that some sharp Linux Journal reader will have an answer.

Dave Taylor has been hacking shell scripts for a really long time, 30 years. He's the author of the popular Wicked Cool Shell Scripts and can be found on Twitter as @DaveTaylor and more generally at


Dave Taylor has been hacking shell scripts for over thirty years. Really. He's the author of the popular "Wicked Cool Shell Scripts" and can be found on Twitter as @DaveTaylor and more generally at


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Passing argument

Anonymous's picture

Hi all,
I wanted to know if it's possible to pass arguments to the configuration file when we invoke the command kill.

For example we want to change directory to a shell 1 from another shell 2, so:
cd $1
trap "sigusr1" USR1

type command in shell 1:
$ ./

then, i would like type something like this in shell 2:
$ kill -USR1 10482 /home

In this way i can specify the new current directory directly from shell 2.

How can I do it? Is there another workaround??