Process Control

Unix systems provide many tools for managing and monitoring processes that are already running. It is possible to have multiple processes running under the same shell session. Such processes are considered either foreground processes or background processes. The foreground process is simply the process that receives the keyboard input. There can be no more than one foreground process under a given shell session, since keyboard input cannot be sent to multiple processes at once.

However, all processes, both foreground and background, are allowed to send output to the terminal at the same time. It is up to the user to ensure that output is managed properly and not intermixed. Generally it does not make sense to have multiple processes sending output to the same terminal, but it is not forbidden. This is another example of Unix "staying out of the way" rather than enforcing rules that may not always be reasonable.

There are three types of tools for process management, described in the following subsections.

External Commands

Unix systems provide a variety of external commands that monitor or manipulate processes based on their process ID (PID). A few of the most common commands are described below.

ps lists the currently running processes.

shell-prompt: ps [-a]     # BSD
shell-prompt: ps [-e]     # SYSV
            

ps is one of the rare commands whose options vary across different Unix systems. There are only two standards to which it may conform, however. The BSD version uses -a to indicate that all processes (not just your own) should be shown. System 5 (SYSV) ps uses -e for the same purpose. Most modern systems accept the BSD standard. Some, such as most GNU/Linux systems, accept either. Run man ps on your system to determine which flags should be used.

kill sends a signal to a process, which may kill the process, but could serve other purposes. We may want to kill a process after noticing that it is producing incorrect output or has been running too long, indicating that something is wrong. The basic form of the command is:

shell-prompt: kill [-#] PID
            

The PID (process ID) is often determined from the output of ps.

shell-prompt: ps
  PID  TT  STAT      TIME COMMAND
 41167   0  Is     0:00.25 tcsh
 78555   0  S+     0:01.98 fdtd
shell-prompt: kill 78555
            

The signal number is an integer value or signal name (minus the SIG prefix) following a -, such as -9 or -SIGKILL. If not provided, the default signal sent is SIGTERM (terminate), which is signal 15. Run man signal to learn about all the signals that can be issued with kill.

Processes can choose to ignore the SIGTERM signal, or respond in a different way than just terminating. Such processes can be force killed using the SIGKILL (9) signal.

shell-prompt: kill -9 78555
shell-prompt: kill -KILL 78555
            

The pkill command will kill all processes running the program named as the argument. This eliminates the need to find the PID first, and is more convenient for killing multiple processes running the same program.

shell-prompt: pkill fdtd
            
Special Key Combinations

Ctrl+c sends a SIGINT signal to the current foreground process. It is equivalent to kill -INT PID. This usually terminates the process immediately, although it is possible that some processes will ignore the signal, as stated earlier.

Ctrl+z sends a stop (SIGSTSTP) signal to the current foreground process. The process remains in memory, but does not execute further until it receives a continue (SIGCONT) signal (usually sent by running fg).

Ctrl+s suspends output to the terminal. This does not signal the process directly, but has the effect of blocking any processes that are sending output, since they cannot complete the output operation.

Ctrl+q allows output to the terminal to resume, if it has been suspended by Ctrl+s.

Example 3.37. Practice Break

Run find /, then press Ctrl+s to suspend output, press Ctrl+q to resume it, press Ctrl+z to stop the process, run fg to continue the process, and press Ctrl+c to terminate the process.


Shell Features for Job Control

An & at the end of any command causes the command to be immediately placed in the background. It can be brought to the foreground using fg at any time. Normally, we do not want background processes sending any output to the terminal, so redirection is usually used at the same time.

jobs lists the processes running under the current shell, but using the shell's job IDs instead of the system's process IDs.

shell-prompt: find / >& output.txt &
[1] 89227
shell-prompt: jobs
[1]  + Running                       find / >& output.txt
            

fg brings a background job into the foreground. It optionally takes a shell job number as an argument. This only matters if there are multiple background jobs running. It can now be terminated using Ctrl+c. There cannot be another job already running in the foreground. If no job ID is provided, and multiple background jobs are running, the shell will choose which background job to bring to the foreground. A job ID should always be provided if more than one background job is running.

shell-prompt: fg 1
find / >& output.txt
^C
shell-prompt:
            

bg resumes a stopped job, such as a foreground job stopped by Ctrl+z, but in the background.

shell-prompt: find / >& output.txt
/
/.snap
/dev
/dev/log
/dev/dumpdev
/dev/cuse
Ctrl+z
shell-prompt: bg
shell-prompt:
            

nice runs a process with limited priority. We use this when we are not concerned about how fast the job runs and want other processes to have more CPU time, so they can complete sooner or respond to user input more quickly.

shell-prompt: nice command
            

If (and only if) other processes in the system are competing for CPU time, they will get a bigger share than processes run under nice.

nohup allows you to run a command that will continue after you log out. Naturally, all input and output must be redirected away from the terminal in order for this to work.

Bourne shell and compatible:

shell-prompt: nohup ./myprogram < inputfile > outputfile 2>&1
            

C shell and compatible:

shell-prompt: nohup ./myprogram < inputfile >& outputfile
            

This is often useful for long-running commands and where network connections are not reliable, or you simply don't want to remain logged in until it's finished.

There are also free add-on programs such as GNU screen that allow a session to be resumed if it's disrupted for any reason.

Practice

Note

Be sure to thoroughly review the instructions in Section 2, “Practice Problem Instructions” before doing the practice problems below.
  1. What is the difference between a foreground process and a background process? How many of each can be running under a given shell process?

  2. How do we keep the output of many background processes from mixing together?

  3. Show a Unix command that terminates process 8210 if kill 8210 has no effect.

  4. What can we do if we have many processes running a program called fastqc and we want to terminate all of them?

  5. What is the easiest way to terminate the foreground process?

  6. How can we temporarily stop the foreground process, run ls under the same shell, and then continue the previous process.

  7. How can we pause output from processes in a terminal, inspect it, and then allow it to continue?

  8. How can we stop the current foreground process and resume it as a background process?

  9. Show a Unix command that runs ./analysis so that its process uses less CPU time than other processes.

  10. Show a Unix command that runs ./analysis so that it will continue running even after we log out.