Work the Shell - Dealing with Signals
This month, I thought it would be interesting to take a bit of a detour from my usual multi-month programming projects and instead focus on a specific topic that is of great importance to people writing longer scripts: signal management.
Signals are numeric messages sent to running applications from the operating system, other applications or the user, and they generally invoke a specific response like “shut down gracefully”, “stop running so I can put you in the background” or “die!”
Most likely, you've used the kill command to send signals to different programs, but if you've ever pressed Ctrl-C or Ctrl-Z to stop a running app, you've also sent signals to a running application.
A signal is managed in a cascading manner. It's sent to the application or script, then if the application doesn't have a specific handler (signal management or response function), it's pushed back to the shell or operating system. Some signals can't be managed within individual apps, like SIGKILL, which is caught by the operating system and immediately kills the running application (including the shell: SIGKILL your login shell and you just logged out).
To start this journey, let's find out what signals your version of Linux can handle. Do this by typing kill -l (that's a lowercase L, not the digit 1):
$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGEMT 8) SIGFPE 9) SIGKILL 10) SIGBUS 11) SIGSEGV 12) SIGSYS 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGURG 17) SIGSTOP 18) SIGTSTP 19) SIGCONT 20) SIGCHLD 21) SIGTTIN 22) SIGTTOU 23) SIGIO 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGINFO 30) SIGUSR1 31) SIGUSR2
Most of these are uninteresting. The cool ones are SIGHUP, which is sent on a “hangup” or the user logging out; SIGINT, which is a simple interrupt (Ctrl-C, usually); SIGKILL, the “terminate with extreme prejudice” of signals; SIGTSTP, which is Ctrl-Z; SIGCONT, which is what the application gets from the shell commands fg and bg subsequent to a SIGTSTP; SIGWINCH, which is for window system events like a window resize; and SIGUSR1 and SIGUSR2, which are intended for interprocess communication.
Let's write some code to see what happens, shall we? Signals are caught with the “trap” built in, and the general format of these signal mapping commands is exemplified with:
trap 'echo "Ctrl-C Ignored" ' INT
How do we play with that as a shell script? Here's an easy way:
#!/bin/bash trap 'echo " - Ctrl-C ignored" ' INT while /usr/bin/true ; do sleep 30 done exit 0
Did you catch the infinite loop there? It's barely using any resources because most of its time is spent in “sleep”, but if you don't do something to end it, this script will run forever or until the Mayans are proven right two years from now—one of the two.
Let's look at a more flexible way to manage signals by creating shell script functions:
sigquit()
{
echo "signal QUIT received"
}
sigint()
{
echo "signal INT received, script ending"
exit 0
}
trap 'sigquit' QUIT
trap 'sigint' INT
trap ':' HUP # ignore the specified signals
echo "test script started. My PID is $$"
while /usr/bin/true ; do
sleep 30
done
Run this then from another terminal window and shoot some signals at it.
Now, let's get that script started and watch what happens when we send a few different signals:
$ ./test.sh test script started. My PID is 25309 signal QUIT received signal INT received, script ending $
Perfect! To send the signals, execute the following commands from a different terminal window:
$ kill -HUP 25309 $ kill -QUIT 25309 $ kill -INT 25309
Armed with this useful script, let's have a look at how to handle a more complex signal like Ctrl-Z within a shell script.
I'm going to create a scenario here rather than just going through the intellectual exercise. In a complex script, you realize that you have certain passages where you need to ignore the TSTP signal (SIGTSTP or Ctrl-Z or signal number 18) and other spots where it's fine to stop and restart. Can it be done?
To start working out a solution, I'll create a function that not only handles the specified signal, but also disables itself after a single invocation:
sigtstp()
{
echo "SIGTSTP received" > /dev/tty
trap - TSTP
echo "SIGTSTP standard handling restored"
}
Invoke trap - signal somewhere else in the script, and you've reset that signal handler, so if I have the line:
trap 'sigtstp' TSTP
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 www.DaveTaylorOnline.com.
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Designing Electronics with Linux | May 22, 2013 |
| Dynamic DNS—an Object Lesson in Problem Solving | May 21, 2013 |
| Using Salt Stack and Vagrant for Drupal Development | May 20, 2013 |
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
- New Products
- Linux Systems Administrator
- Senior Perl Developer
- Technical Support Rep
- UX Designer
- Web & UI Developer (JavaScript & j Query)
- Designing Electronics with Linux
- Dynamic DNS—an Object Lesson in Problem Solving
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Using Salt Stack and Vagrant for Drupal Development
- Reply to comment | Linux Journal
22 min 54 sec ago - Nice article, thanks for the
11 hours 3 min ago - I once had a better way I
16 hours 49 min ago - Not only you I too assumed
17 hours 6 min ago - another very interesting
18 hours 59 min ago - Reply to comment | Linux Journal
20 hours 53 min ago - Reply to comment | Linux Journal
1 day 3 hours ago - Reply to comment | Linux Journal
1 day 4 hours ago - Favorite (and easily brute-forced) pw's
1 day 5 hours ago - Have you tried Boxen? It's a
1 day 11 hours ago
Enter to Win an Adafruit Pi Cobbler Breakout Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Pi Cobbler Breakout Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- 5-21-13, Prototyping Pi Plate Kit: Philip Kirby
- Next winner announced on 5-27-13!
Featured Jobs
| Linux Systems Administrator | Houston and Austin, Texas | Host Gator |
| Senior Perl Developer | Austin, Texas | Host Gator |
| Technical Support Rep | Houston and Austin, Texas | Host Gator |
| UX Designer | Austin, Texas | Host Gator |
| Web & UI Developer (JavaScript & j Query) | Austin, Texas | Host Gator |
Free Webinar: Hadoop
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers
Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.
Some of key questions to be discussed are:
- What is the “typical” Hadoop cluster and what should be installed on the different machine types?
- Why should you consider the typical workload patterns when making your hardware decisions?
- Are all microservers created equal for Hadoop deployments?
- How do I plan for expansion if I require more compute, memory, storage or networking?




Comments
Passing argument
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:
# test.sh
sigusr1()
{
cd $1
}
trap "sigusr1" USR1
type command in shell 1:
$ ./test.sh
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??
Thanks