Guide to Unix/Explanations/Signals
Signals
editSignals 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
editProcesses 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
editCommands 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