Main index

Introducing UNIX and Linux


Processes and devices

Overview
Processes
      Process status
      Foreground and background
      Process control
      Signals
Environment
      Environment variables
      Global and local variables
      Executable scripts
Program control
      Job control
      Command history list
      Running a job at a specific time
      Running programs periodically
      Big programs
      Timing a program
      Running programs in order
Quotes and escapes
Devices
Backquotes
Summary
Exercises

Job control

A job is a collection of processes grouped together and identified by a small integer. In the example above, the job number for process 16403 was 1. When a UNIX command is sent to the background using &, a single job is created consisting of one or more processes. That job will initially be sent to the background, but can be moved into the foreground or destroyed in much the same way as an individual process. Consider the following pipe:

cat testfile | wc &
[2] 2374

A single job (number 2) has been created in the background, but two processes are required, one for cat and one for wc. The process number 2374 is that of the last command in the pipe, namely wc. You can destroy the job, and consequently both processes, with

kill -s KILL %2

(instead of giving the command kill the number of the process to send a signal to, we give it the number of the job preceded by a percent character).

Worked example

Arrange to be given an 'alarm call' after 2 minutes.
Solution: Create a script that uses sleep to cause it to suspend for 120 seconds, and then use echo to write a message to your screen. The script should be run in the background.

cat >myalarm
sleep 120
echo Your alarm call ...

ctrl-D
sh myalarm &

If you now typed ps, you would find (amongst others) two processes:

23624 p2 S 0:00 sh myalarm
23625 p2 S 0:00 sleep 120

indicating that both the script myalarm and the command sleep had been invoked. You could,, of course, have used vi to create myalarm.

You may have several jobs running at any one time, and command jobs will list them. For example,

jobs
[1] Stopped testA
[2]- Running sh myalarm &
[3]+ Running testB &

indicates that you have 3 jobs. Jobs 2 and 3 are running in the background, whereas number 1 has been stopped. Note that the word Suspended is used on some systems instead of Stopped. This means that the system is not running that job at all; it is suspended pending reactivation. You can try creating a few jobs yourself - the script myalarm from the last worked example is suitable to experiment with. Take a copy of myalarm, call it (say) newalarm, and execute both in the background; you should get a dialogue similar to:

cp myalarm newalarm
sh myalarm &
[1] 25816
sh newalarm &
[2] 25820
jobs
[1]- Running sh myalarm &
[2]+ Running sh newalarm &

If you have jobs running or stopped, one of them will be the default job, and is indicated in the output from jobs by the symbol + after its number - in the above example this would be job 3. The default job is the job that was most recently created (or sent a signal by you). If you have two or more running, one will be indicated by a - symbol, which indicates that if the default job was to terminate, this one would then become the default. In the example above this would be job 2. The default job is also known as %%.

Any job that is in the background or is stopped can become the foreground job simply by giving the job number (preceded by %) as argument to the command fg ('foreground'). Similarly, any stopped job can be reactivated to run in the background by the command bg ('background'):

bg %1
[1]+ testA &
jobs
[1] Running testA
[2]- Running sleep 120 &
[3]+ Running testB &
fg %%

The reason for having default jobs is that quite often, when you have sent a job into the background, you will either want it to be brought back to the foreground or perhaps killed. In practice, you tend to find that you have not created any new jobs in the meantime, and it is useful to have a shorthand for referring to the default job.

Any job sent to the background will still have its standard output and standard error streams set up as if the job were still in the foreground. What this means for the user is that if a background job wants to write to your terminal, it will do so (so you should not be surprised if, when running jobs in the background, messages do appear on your screen). Yet any input you type on your terminal will be sent to the current foreground process or to the shell - if you had many background processes running, the system couldn't be expected to decide which job your input was intended for, so can only send it to a foreground process.

A background job must therefore do something sensible if it requires input from the terminal. What happens in this case is that the background job automatically stops - a signal called SIGTTIN is sent to it when it attempts to read from the terminal, and this signal has the effect of stopping the job. Consider:

cat &
[1] 13249
$
[1]+ Stopped (SIGTTIN) cat

The command cat, in the absence of any arguments, reads from standard input; cat is run in the background, so immediately demands input, but since it is in the background it cannot receive it. It therefore becomes suspended and you are sent a message to tell you of this fact.

If you send a job to the background that requires input from your terminal, it will become stopped as soon as it requires that input, and you must bring it to the foreground if you wish it to complete executing. Try this with mailx:

mailx -s "Test" chris &
[1] 24545
[1]+ Stopped (SIGTTIN) mailx
fg %1

(you can type in your message now)


Copyright © 2002 Mike Joy, Stephen Jarvis and Michael Luck