Job control is a function of the shell that executes multiple commands simultaneously and suspends/resumes the commands.

When job control is active:

  • Every pipeline executed by the shell becomes a job. A job has its unique process group ID that is shared among all processes in the job.

  • If the processes of a job are suspended while the shell is waiting for the processes to finish, the shell continues to the next command as if the process have finished. The shell remembers the job as suspended so that it can be resumed later.

  • If a job is executed synchronously, the shell sets the foreground process group of the terminal to the process group of the job. When the job is finished (or suspended), the shell gets back to the foreground.

  • If the shell is interactive, job status is reported before every command line prompt as if the command jobs -n is executed.

  • The standard input of an asynchronous command is not automatically redirected to /dev/null.

  • The shell does not stop when it receives the SIGTTIN, SIGTTOU, or SIGTSTP signal.

  • The value of the - special parameter contains m.

  • When a job finished for which the wait built-in has been waiting, the fact is reported (only if the shell is interactive and not in the POSIXly-correct mode).

When job control is inactive, processes executed by the shell have the same process group ID as the shell. The shell treats asynchronous commands as an uncontrolled job.

You can use the following built-ins to manipulate jobs:

jobs

prints existing jobs

fg and bg

run jobs in the foreground or background

wait

waits for jobs to be finished (or suspended)

disown

forgets jobs

kill

sends a signal to jobs

An interactive job-controlling shell reports jobs status before every prompt by default. You can set the following options to make the shell report status at other timings:

notify

the shell reports immediately whenever job status changes.

notify-le

the shell reports immediately when job status changes while line-editing.

A job is removed from the shell’s job list when:

Jobs are not removed from the list when an interactive shell automatically reports the status of jobs.

Note
The word “stop” is synonymous to “suspend” in the context of job control.

Job ID

Some built-ins use the following notation, which is called job ID, to specify a job to operate on:

%
%%
%+

the current job

%-

the previous job

%n

the job that has job number n, where n is a positive integer

%string

the job whose name begins with string

%?string

the job whose name contains string

The current job and previous job are jobs selected by the shell according to the following rules:

  • When there is one or more suspended jobs, the current job is selected from them.

  • When there is one or more suspended jobs other than the current job, the previous job is selected from them.

  • The current and previous jobs are always different. When the shell has only one job, it is the current job and there is no previous job.

  • When the current job finished, the previous job becomes the current job.

  • When the current job is changed, the old current job becomes the previous job except when the old job finished.

  • When the foreground job is suspended, the job becomes the current job.

Yash has some options to modify the rules of the current/previous job selection. (The rules above have priority over the options below.)

cur-async

When a new asynchronous command is started, it becomes the current job.

cur-bg

When a job is resumed by the bg built-in, the job becomes the current job.

cur-stop

When a job is suspended, it becomes the current job.

The current and previous jobs are not changed as long as the rules above are met.

The rules of the current/previous job selection defined in the POSIX standard are looser than yash’s rules above. Other POSIX-compliant shells may select the current and previous jobs differently.