Job Control

Job Control

Job control is the ability to move processes between the foreground and background. This is very useful when you need to do several things at once, but only have one terminal. For example, let’s say there are several files spread out across the system that we want to edit. Because we don’t know where they are, we can’t use full paths. Because they don’t have anything common in their names, we can’t use find. So we try ls -R > more.

After a minute or two, we find the first file we want to edit. We can then suspend this job by pressing Ctrl+Z. We then see something that looks like this:

[1]+ Stopped ls -R | more

This means that the process has been stopped or suspended. One very important thing to note is that this process is not in the background as if we had put an “&” at the end. When a process is suspended, it stops doing anything, unlike a process in the background, which keeps on working.

Once the ls is in the background, we can run vi. When we are done with vi, we can bring the ls command back with the fg (foreground) command.

If we wanted to, we could have more than just one job suspended. I have never had the need to have more than two running like this, but I have gotten more than ten during tests. One thing that this showed me was the meaning of the plus sign (+). This is the “current” job, or the one we suspended last.

The number in brackets is the process entry in the job table, which is simply a table containing all of your jobs. Therefore, if we already had three jobs, the next time we suspended a job, the entry would look like this:

[4]+ Stopped ls -R >> output

To look at the entire job table, we simply enter the command jobs, which might give us

[1] Stopped ls -R /usr >> output.usr
[2] Stopped find / -print > output.find
[3]- Stopped ls -R /var >> output.var
[4]+ Stopped ls -R >> output.root

The plus sign indicates the job that we suspended last. So this is the one that gets called if we run fg without a job number. In this case, it was Job 4. Note that there is a minus sign (-) right after Job 3. This was the second to last job that we suspended. Now, we bring Job 2 in the foreground with fg 2 and then immediately suspend it again with Ctrl+Z. The table now looks like this:

[1] Stopped ls -R /usr >> output
[2]+ Stopped find / -print > output.find
[3] Stopped ls -R /var >> output
[4]- Stopped ls -R >> output

Note that Job 2 now has the plus sign following it and Job 4 has the minus sign.

In each of these cases, we suspended a job that was running in the foreground. If we had started a job and put it in the background from the command line, the table might have an entry that looked like this:

[3] Running ls -R /var >> output &

This shows us that although we cannot see the process (because it is in the background), it is still running. We could call it to the foreground if we wanted by running fg 3. And, if we wanted, we could use the bg command to send one of the stopped jobs to the background. So

bg %1

would send Job 1 to the background just as if we had included & from the command line.

One nice thing is that we don’t have to use just the job numbers when we are pulling something into the foreground. Because we know that we started a process with the find command, we can get it by using

fg %find

Actually, we could have used %f or anything else that was not ambiguous. In this case, we were looking for a process that started with the string we input. We could even look for strings anywhere within the command. To do this, the command might be

fg %?print

which would have given us the same command. Or, if we had tried

fg %?usr

we would have gotten Job 1 because it contains the string usr.

If we find that there is a job that we want to kill (stop completely), we can use the kill command. This works the same way, so kill %<nr> kills the job with number <nr>, kill %<string> kills the job starting with string, and so on.

Keep in mind that process takes up resources whether they are in the foreground or not. That is, background processes take up resources,too.

If you do not remember the process ID of the last process that was placed in the background you can reference it any time using the $! system variable. You can also use the wait command to stop processing until the particular process is done. The syntax is simply:

wait PID

Although generally considered part of “job control” you can change the default priority a process has when it starts, as well as the process of a running process. Details of this can be found in the section on process scheduling.