Signals and Scripts
This article explains what UNIX signals are and why
you might want
to catch them in a shell script. I take a look at the
abilities of the Bourne and Korn shells, the C shell,
and perl. Examples
show how you can use signal handling to make your system
When an important asynchronous event occurs, the operating
sends a signal to the affected process. Signals are
interrupts, because they interrupt the normal execution
of a process.
Some events that can cause signals to be sent are hanging
connection, typing Control-C, dividing by zero, and
running out of
When you type Control-C, for example, the operating
system sends a
SIGINT signal to the process in the foreground. If you
at the shell prompt or typing a command line, this process
login shell; otherwise, it is the process you are running
(in a pipe,
usually the final process).
If the process receiving the signal is a shell interpreting
you can write the script to catch some signals and do
in response. For example, when the user types that Control-C,
default action of a shell is to stop executing the script,
leave an untidy mess of temporary files behind.
You can write the script to remove temporary files and
other cleanup actions. You can even choose to ignore
though a Control-Z can stop the process. Then the process
can be killed.
Table 1 shows some signals that are found in most flavors
These are the signals that can originate from something
a user does.
There are many other signals, corresponding to such
as illegal instructions, memory errors, and so on. It
no sense for a shell script to catch such signals.
Signals may be referenced by name or by number. In Bourne
and C shell
scripts you use the signal number; in perl, you use
the name but without
the "SIG". See /usr/include/sys/signal.h and
pages for kill, signal, and termio for detailed
information on the signals supported by your operating
You can do one of three things with these signals. Let
the shell take
its default action (terminate the script). Ignore the
the signal and do something useful.
As an aside, when you fork a child process and then
wait for it to
terminate, you are using signal handling. The parent
a signal when a child process dies. The wait just puts
to sleep until this happens.
There are some basic differences in the signal handling
of the three script languages (the Bourne and Korn shells
same facilities). The Bourne shell provides a facility
an arbitrary sequence of commands on any signal and
also on normal
exit (signal "0"). The latter is very handy
for doing miscellaneous
cleanup like removing temporary files. Different sequences
can be associated with different signals.
The C shell provides a transfer of control on signals,
but does not
implement the useful "normal exit" signal
of the Bourne shell.
One transfer point is used to handle all signals, and
there is no
way to resume processing after handling a signal. In
a C shell script
you can use this transfer to clean up temporary files
but that is pretty much the extent of what you can do
-- just one
more reason why the C shell is the last choice for writing
administration scripts. (Some other reasons are the
redirecting standard error and the lack of shell procedures.)
The rich and wonderful perl language lets you specify
to be executed for each signal. A common signal handler
tell which signal has occurred (the name of the signal
to the handler routine as an argument). Version 5 of
an "END" action much like that of awk that
used to clean up at termination.
The first example is looking through the files in a
user's home directory
and compiling a list of files for likely removal. The
list is in the
common "ls -lR" format, which shows the maximum
information without generating excessively long path
names that tend
to wrap around on the monitor. The user is given several
to how to proceed: quit, generate a file of removal
commands for later
execution (perhaps after editing, and to serve as a
record of what
is removed), or interactive removal right now. Figure
1 is an example
Bourne shell implementation; Figure 2 is the perl version.
This example makes a very simple match against filename
You may want to use a longer list of suffixes, plus
for files older than, say, two years, of size zero,
larger than some
maximum size, and so on. The last time my server crashed
the disks were fsck'd, I noticed that there were over
user files. I bet there is some deadwood in there! I'm
going to be
encouraging my users to use this script, you betcha.
Figure 3 is an example Bourne shell script that waits
If the user hits Control-C, he or she is informed of
the time remaining
to wait, but the wait goes on. Figure 4 is an attempt
at doing this
in the C shell. It illustrates the shortcomings of the
C shell in
Figure 5 shows how to use the BEGIN and END actions
in version 5 of
perl. Version 5 of perl is now available and I encourage
you to make
the switch. Scripts written in perl version 4 will work
5 with little or no modification.
Which Script Language?
The Bourne shell is undoubtedly the first choice for
administration scripts. This shell is found on all UNIX
with little or no variation. If your scripts must run
use the Bourne shell.
Although the Korn shell offers many enhancements for
it is basically identical to the Bourne shell for writing
The Korn shell is not commonly found on BSD systems.
Bash (The FSF's Bourne again shell) is acceptable and
is freely available,
but is of course not found on all systems. Because perl
to be available on any system that has Bash, I would
Bash, except that for true portability you should make
your Bourne shell scripts run under Bash.
The C shell is now quite common, but it is so weak that
I would not
use it for this purpose. The same comment applies to
perl is the ideal choice for writing system administration
but it is not yet a standard part of most operating
I have heard that Sun intends to distribute perl with
I don't know when this will begin. I do expect that
will be found on any system that dares to call itself
perl programs are scripts in the sense that they remain
form. A perl script is "compiled" each time
it is run, which
is why you are informed of syntax errors before any
action takes place.
With Bourne or C shell scripts, syntax errors are not
that part of the script is executed. (This is why funny
when you edit your .login file. If you start a window
from your .login file, your login shell may still be
the .login file when you quit the window manager and
The shell keeps a pointer to where it should resume
If you edit the .login file, that pointer may now be
middle of a line.)
Making your scripts signal-smart is a good idea. You
can leave fewer
junk files lying around and make life easier for the
perl. By the time you read this, the new improved perl
5 should be
Schwartz, Randal. Learning Perl. Sebastopol, CA: O'Reilly
Associates, 1993. ISBN: 1-56592-042-2.
Wall, Larry, and Randal Schwartz. Programming perl.
CA: O'Reilly & Associates, 1991. ISBN: 0-937175-64-1.
About the Author
John Lees has an M.S. in computer science and has worked
the past twenty years about equally as a teacher, technical
programmer, and system administrator. His computer experience
in the days of front panels and paper tape, and he doesn't
fingers and toes to count the operating systems he has
used. His love/hate
relationship with UNIX dates to early 1985. Currently
Mr. Lees is
a systems analyst with the Department of Computer Science,
of the Pattern Recognition and Image Processing Laboratory,
State University. He is a member of ACM, Computer Professionals
Social Responsibility, the League for Programming Freedom,
the Society for
Technical Communication, and the TeX Users Group.