Classic Shell Scripting - Arnold Robbins [194]
Show the test script
trap 'echo This is an EXIT trap' EXIT
trap 'echo This is a DEBUG trap' DEBUG
pwd
pwd
Now supply this script to several different shells on a Sun Solaris system:
$ /bin/sh debug-trap
Try the Bourne shell
test-debug-trap: trap: bad trap
/tmp
/tmp
This is an EXIT trap
$ /bin/ksh debug-trap
Try the 1988 (i) Korn shell
/tmp
This is a DEBUG trap
/tmp
This is a DEBUG trap
This is an EXIT trap
$ /usr/xpg4/bin/sh debug-trap
Try the POSIX shell (1988 (i) Korn shell)
/tmp
This is a DEBUG trap
/tmp
This is a DEBUG trap
This is an EXIT trap
$ /usr/dt/bin/dtksh debug-trap
Try the 1993 (d) Korn shell
This is a DEBUG trap
/tmp
This is a DEBUG trap
/tmp
This is a DEBUG trap
This is an EXIT trap
$ /usr/local/bin/ksh93 debug-trap
Try the 1993 (o+) Korn shell
This is a DEBUG trap
/tmp
This is a DEBUG trap
/tmp
This is a DEBUG trap
This is an EXIT trap
$ /usr/local/bin/bash debug-trap
Try the GNU Bourne-Again shell
This is a DEBUG trap
/tmp
This is a DEBUG trap
/tmp
This is a DEBUG trap
This is an EXIT trap
$ /usr/local/bin/pdksh debug-trap
Try the public-domain Korn shell
test-debug-trap[2]: trap: bad signal DEBUG
$ /usr/local/bin/zsh debug-trap
Try the Z-shell
This is a DEBUG trap
/tmp
This is a DEBUG trap
/tmp
This is a DEBUG trap
This is an EXIT trap
This is a DEBUG trap
We found older versions of bash and ksh that behaved differently in these tests. Clearly, this variation in behavior for the DEBUG trap is problematic, but it is unlikely that you need that trap in portable shell scripts.
The ERR trap also has a surprise: command substitutions that fail do not trap. Here's an example:
$ cat err-trap
Show the test program
#! /bin/ksh -
trap 'echo This is an ERR trap.' ERR
echo Try command substitution: $(ls no-such-file)
echo Try a standalone command:
ls no-such-file
$ ./err-trap
Run the test program
ls: no-such-file: No such file or directory
Try command substitution:
Try a standalone command:
ls: no-such-file: No such file or directory
This is an ERR trap.
Both ls commands failed, but only the second caused a trap.
The most common use of signal trapping in shell scripts is for cleanup actions that are run when the script terminates, such as removal of temporary files. Code like this trap command invocation is typical near the start of many shell scripts:
trap 'clean up action goes here' EXIT
Setting a trap on the shell's EXIT signal is usually sufficient, since it is handled after all other signals. In practice, HUP, INT, QUIT, and TERM signals are often trapped as well.
To find more examples of the use of traps in shell scripts, try this on your system:
grep '^trap' /usr/bin/* Find traps in system shell scripts
Most scripts that we found this way use old-style signal numbers. The manual pages for the signal( ) function should reveal the correspondence of numbers to names.
* * *
[3] A process that is awaiting an event, such as the completion of I/O, or the expiration of a timer, is in a suspended state called a sleep, and the process scheduler does not consider it runnable. When the event finally happens, the process is again schedulable for execution, and is then said to be awake.
Process System-Call Tracing
Many systems provide system call tracers, programs that execute target programs, printing out each system call and its arguments as the target program executes them. It is likely you have one on your system; look for one of the following commands: ktrace, par, strace, trace, or truss. While these tools are normally not used inside shell scripts, they can be helpful for finding out what a process is doing and why it is taking so long. Also, they do not require source code access, or any changes whatsoever to the programs to be traced, so you can use them on any process that you own. They can also help your understanding of processes, so we give some small examples later in this section.
If you are unfamiliar with the names of Unix system calls, you can quickly discover many of them by