Guide to Unix/Explanations/Signals

From Wikibooks, open books for an open world
< Guide to Unix‎ | Explanations
Jump to: navigation, search

Signals[edit]

Signals are software interrupts that notify processes that some condition or event has occurred. Examples of events that generate signals are:

  • a process attempts a divide by zero
  • a user presses the INTERRUPT key at the terminal
  • a process sends another process a signal with the kill command of the kill function

A list of all the different signals can be displayed using

$ kill -l

The kill command can also be used to send signals to other processes. Start a background process that sleeps for 1000 seconds:

$ sleep 1000 &
[1]     14936
$ ps
   PID TTY      TIME CMD
 14936 pts/7    0:00 sleep
 12203 pts/7    0:01 bash

Note that the process id will (most likely) be different when you run it. The command-line below sends the SIGKILL signal to process 14936 (in this case):

$ kill -KILL 14936
$ ps
   PID TTY      TIME CMD
 12203 pts/7    0:01 ksh
[1] + Killed                   sleep 1000 &

Upon receiving the SIGKILL signal the sleep process terminates.

Traps[edit]

Processes can respond to signals in three different ways:

  • perform the default action
  • ignore the signal.
  • execute a specified function (called a signal handler)

The default action performed by a process when it receives a signal depends on the signal type. Most (like SIGKILL) cause the process to terminate. Others like SIGQUIT cause the process to terminate and generate a core dump:

$ sleep 1000 &
[1]     14950
$ kill -QUIT 14950
$ ps
   PID TTY      TIME CMD
 12203 pts/7    0:01 bash
[1] + Quit(coredump)           sleep 1000 &
$ ls core
core

Core files can be large so delete it:

$ rm core

Signals can be caught using the trap command. Create the following shell script in the file catch_signal.sh:

#!/bin/bash
trap 'echo "GOTCHA!"' INT KILL
while :
do sleep 10
done

Run catch_signal.sh in background:

$ catch_signal.sh &
[1]     15053
$ kill -INT 15053
$ GOTCHA!

The signal was caught and instead of terminating (which is the default action for SIGINT) the message "GOTCHA!" was echoed to standard output.

Some signals however can't be caught, SIGKILL for example:

$ kill -KILL 15053
[1] + Killed                   catch_signal &

Run catch_signal.sh; in foreground:

$ catch_signal

Hit the interrupt key (control-C usually):

^CGOTCHA!

Now hit the quit key:

^\catch_signal[3]: 15102 Quit(coredump)
$ ls core # will have generated a core file
core

Nohup[edit]

Commands run with nohup do not terminate when the user logs off.

Create the script in the file dont_hangup.sh and make it executable:

#!/bin/bash

while :
do
    date
    sleep 100
done

Run it in background preceded by the command nohup:

$ nohup dont_hangup.sh &
[1]     15224
Sending output to nohup.out

Check its running: id (12203 in this case):

$ ps -fu aholt
aholt 15224 12203 pts/7  sh ./dont_hangup.sh
aholt 15232 15224 pts/7  sleep 100

Make a note of the parent process id (12203 in this case) of "dont_hangup" and the terminal device and log out of your session.

Log back in again. See that dont_hangup.sh is still running:

$ ps -fu aholt
aholt 15224      1 ? 0:00 sh ./dont_hangup.sh
aholt 15237 15224  ? 0:00 sleep 100

While "dont_hangup.sh" is still running, its parent process has changed. The process id of the parent is 1 (not 12203 as before) and it is no longer associated with a terminal device. Using nohup is equivalent to ignoring the SIGHUP, that is:

trap '' HUP