Unix: Job control

Processes

Manipulating Unix processes used to be an important aspect of mastering Unix back in the old days when a Unix “terminal” actually was a physical CRT terminal – and you only had one. If your terminal was attached to a busy process, and you needed to run a second process, you would have to borrow asecond CRT terminal from a collegue. Or, instead of borrowing a terminal, you could detach a process from your terminal by putting it in the background, thereby making the terminal available again.

These days, Unix “terminals” tend to be windows on a bitmapped screen, and you can have so many as you want. Hence, most of the reasons for having a need to manipulate processes has vanished. But process manipulation is still part of Unix. If you want to learn it, here are the basics.

Information about processes

A process is an executing program identified by a unique PID (process identifier). To see information about your processes, with their associated PID and status, type:

$ ps

A process may be in the foreground, in the background, or be suspended. In general the shell does not return the Unix prompt until the current process has finished executing.

Some processes take a long time to run and make the terminal unavailable to the user. Backgrounding a long process has the effect that the Unix prompt is returned immediately, and other tasks can be carried out while the original process continues executing.

Backgrounding a process

To background a process, type an & at the end of the command line.

To demonstrate, I shall use the command sleep. This is a standard command that just sleeps (waits) a given number of seconds before completing. The command sleep 10 will sleep for 10 seconds before terminating. Until the command has terminated, your terminal will be uanavailable, and you will not be able to type in another command.

To run sleep in the background, instead of typing:

$ sleep 10

you type:

$ sleep 10 &
[1] 18156
$

The & at the end of the command line tells the shell to run the job in the background (i.e. detached from the termibal) and to give you back the command line prompt straight away. This allows you do run other programs in the same terminal while waiting for that one to finish.

The first line in the above example is typed in by the user. The next line, indicating job number and PID, is returned by the machine. The third line shows that the command line prompt is available again instantly, before the sleep command has terminated.

The second line shows how the shell reports that a job is put in the background. The job number (numbered from 1) is enclosed in square brackets. The PID (18156 in the example above) is a system-wide unique identifier.

Backgrounding, usually together with redirection of output, is sometimes useful for jobs which will take a long time to complete.

Listing background and stopped processes

When a process started from the current shell is backgrounded or stopped, it will be entered onto a list along with a job number. To examine this list, use the jobs command.

An example of a list of job could be:

$ jobs
[1]  Running sleep 600
[3]- Stopped ls -R | more
[4]+ Stopped vim

The number in square brackets is the job's jobnumber. The + sign indicates that this job was stopped last. This is also known as the current job. The - sign indicates that this job was the second to last job to be stopped.

To put in the foreground the current job, just type:

$ fg

Given the list of jobs in the example above, this will restart job number 4 (vim).

To put in the foreground a specific process in the job queue, include the jobnumber in the command.

For example, given the list of jobs in the example above, to restart sleep 600, type:

$ fg %1

Notice that there should be a percentage sign in front of the jobnumber.

Backgrounding a current foreground process

You can also place a process currently running in the foreground in the background.

To try this out, at the comamnd line prompt, type:

$ sleep 600

This starts a process that will just sleep for 600 seconds (10 minutes) and places it in the foreground.

To regain the terminal before the 10 minutes are up you can suspend (stop) the process running in the foreground by typing [Ctrl]-Z. If we examine the jobs queue afterwars we will see something similar to this.

$ jobs
[3]- Stopped ls -R | more
[4]  Stopped vim
[5]+ Stopped sleep 600

However, we the job to continue running, but in the background. Since it is the current process, as indicated by the +, the following command will do that:

$ bg

Re-examining the jobs queue, we see that it is now running:

$ jobs
[3]+ Stopped ls -R | more
[4]  Stopped vim
[5]- Running sleep 600

If we try the same trick with job 4 (vim), it won't work. It becomes running, but is immediately stopped again. This is because vim (an interactive text editor) is unable to run unless it is attached to the terminal. Non-interactive programs such as sleep is fine running in the background, but interactive programs such as vim must be in the foreground to run.

Terminate (kill) a process

It is sometimes necessary to kill a process (for example, when an executing program becomes totally unresponsive due to some error).

To kill a job running in the foreground, type [Ctrl-]-C). For example;

$ sleep 600
[Ctrl]-C
$

To kill a suspended or background process, type kill %jobnumber. For example:

$ sleep 600 &
$ jobs
[3]+ Stopped ls -R | more
[4]  Stopped vim
[5]- Running sleep 600
$ kill %5
[5]- Terminated   sleep 600
$ jobs
[3]+ Stopped ls -R | more
[4]- Stopped vim

In this example, the job with jobnumber 5 was killed.

Instead of using the job number to identify the process to kill, you can use its PID. You can use the command ps to find PIDs. Example:.

$ ps
  PID TTY       TIME CMD
 4218 pts/1 00:00:00 bash
 9816 pts/1 00:00:22 vim
12867 pts/1 00:00:00 sleep
12879 pts/1 00:00:00 ps
$ kill 12867
$
[5]- Terminated   sleep 600

When using the kill command, a signal is sent to the process. The default signal only request that the process terminates. The process is expected to clean up by flushing buffers, closing open files, etc., and then terminate. However, the process is free to ignore it.

If a process ignores the default signal, it can still be killed with the following command:

$ kill -9 PID

This sends signal 9 to the process identified by PID. Signal 9 can't be handled or ignored. This is pretty brutal, since the process can't handle the signal, it can't clean up before terminating.

It is not possible (unless you're root) to kill off other users' processes.

Summary

Command Meaning
command & run command in background
[Ctrl]-Z suspend the job running in the foreground
[Ctrl]-C kill the job running in the foreground
jobs list current jobs
ps list current processes
bg %jobnumber place jobnumber in the background
fg %jobnumber place jobnumber in the foreground
kill %jobnumber kill (signal) process with jobnumber
kill number kill process number