17.9. Process Control

When you run a program or command at the shell prompt, the shell usually creates a new process that will run the program or command (a process is the operating systems abstraction of a running program). There are a few built-in shell commands that the shell process executes itself (e.g., cd), but most are run as separate processes. See Chapter 13: The Operating System for more information about processes.

The unix shell supports process control features, which are ways to specify how a program is run by the shell, and ways to interact with the process as it runs.

17.9.1. Running in the foreground and background

When a program is run at the shell prompt, it runs in the foreground by default, meaning that the program runs to completion before the shell program runs again and prints out the next prompt. However, programs can also be run in the background, meaning that the shell starts the program running but does not wait until it completes before printing out the next prompt; this allows a user to enter another command while the program is still running. To tell the shell to run a program in the background, the user adds an & at the end of the command line. For example, here is how to tell the shell to run an a.out program in the background:

$ ./a.out &
$

The ps command can be used to list all the programs running in the shell. For example, here we start two a.out programs running in the background, and then type ps:

$ ./a.out &
$ ./a.out &
$ ps
    PID TTY          TIME CMD
 2729   pts/72    0:03.91 bash
 3582   pts/72    0:00.00 ./a.out
 3583   pts/72    0:00.00 ./a.out
 3584   pts/72    0:00.00 ps

In the example output, you can see two a.out processes are running in addition to the Bash shell process and the ps process. With each process is listed its process id, a unique identifier the the operating system keeps for each process (i.e., the bash process id is 2729 and the two processes running the a.out program have process ids 3582 and 3583).

A process running in the background can be moved to the foreground using the fg command:

$ ./a.out &     # run a.out in the background
$ ps
    PID TTY          TIME CMD
 2729   pts/72    0:03.91 bash
 3584   pts/72    0:00.00 ./a.out

$ fg           # move a.out to the foreground (the shell waits for it to exit)

$ ps           # run ps at the shell prompt (a.out has exited)
    PID TTY          TIME CMD
 2729   pts/72    0:03.91 bash

By typing CTRL-Z a process running in the foreground can be interrupted and suspended meaning that its execution is paused (it is not running). This causes the shell to run again and print out a shell prompt. If the user types bg, the suspended process will continue running, but now run in the background. If the user types fg the suspended process will continue running in the foreground again. Here are some examples:

$ ./a.out     # run a.out in the foreground
              # type CTRL-Z to suspend a.out
[1]  Stopped                 ./a.out

$ ps
    PID TTY          TIME CMD
 2729   pts/72    0:03.91 bash
 3588   pts/72    0:00.00 ./a.out

$ bg         # unsuspend a.out and run in background

$ ps
    PID TTY          TIME CMD
 2729   pts/72    0:03.91 bash
 3588   pts/72    0:00.00 ./a.out

$ fg        # run backgrounded process in the foreground

17.9.2. Killing a running processes

The kill and pkill commands are used to send a signal from the shell process to another processes. Signals are a way in which one process can notify another process to do something. Every signal triggers a default behavior, exiting or ignoring are two common default options (see Chapter 13: The Operating System for more information about signals).

The kill command takes the process id (PID) of the process to send the signal, and the pkill command takes the name of the command or executable file to which to send the signal (pkill sends the signal to all running processes with the specified name that are owned by the user running pkill). Both kill and pkill take an optional command line argument that species the specific signal to send to the process. Without specifying the specific signal, both default to sending a termination signal (SIGTERM) to the specified process(s).

A common use of these commands is to send a process a signal to tell it to exit (this is where kill gets its unfortunate name). Note that a process running in the foreground also can be killed by typing CTRL-C, which sends the process running in the foreground a SIGINT signal that by default tells the process to exit.

Here is an example call to pkill to kill all a.out processes:

$ ps
    PID TTY          TIME CMD
3032597 pts/72   00:00:00 bash
3033074 pts/72   00:00:04 a.out
3033076 pts/72   00:00:03 a.out
3033089 pts/72   00:00:02 a.out
3033105 pts/72   00:00:00 ps

$ pkill a.out
[1]   Terminated              ./a.out
[2]-  Terminated              ./a.out
[3]+  Terminated              ./a.out

$ ps
    PID TTY          TIME CMD
3032597 pts/72   00:00:00 bash
3033128 pts/72   00:00:00 ps

Here is an example call to kill to kill a specific a.out processes given its PID (the second process in the first ps listing):

$ ps
    PID TTY          TIME CMD
3032597 pts/72   00:00:00 bash
3033870 pts/72   00:00:03 a.out
3033883 pts/72   00:00:02 a.out
3033886 pts/72   00:00:01 a.out
3033897 pts/72   00:00:00 ps

$ kill 3033883
[2]-  Terminated              ./a.out

$ ps
    PID TTY          TIME CMD
3032597 pts/72   00:00:00 bash
3033870 pts/72   00:00:18 a.out
3033886 pts/72   00:00:16 a.out
3033974 pts/72   00:00:00 ps

Note that kill only killed the specific process with a matching pid value and not every process running the same program (a.out).

In both of these examples, we are not specifying the signal to send. Without any optional command line options, kill and pkill send the process the terminate signal (SIGTERM or signal number 15). By default, SIGTERM tells the signaled process to exit. Sometimes you will see calls to kill and pkill that include a different signal number. In this case the signal number is specified as a command line argument (-<signal number>'). For example, we could have included the signal number `-9 to send them the SIGKILL signal (yet another way to tell a process to exit):

$ pkill -9 a.out
$ kill -9 3033883

In general, these commands can be used to send any signal to a process. For example, to send a process a SIGALRM signal (which is signal number 14), you could do this:

$ kill -14 3033883

If the process doesn’t have a signal handler for the SIGALRM signal, the default behavior is that the SIGALRM signal is just ignored.

The man page for signal lists the minimal set of signals (and their signal numbers) that are defined in the system: man 7 signal.

17.9.3. References

For more information see: