Job control (Unix): Difference between revisions

Content deleted Content added
m Implementation: this just links back here
 
(46 intermediate revisions by 11 users not shown)
Line 1:
{{Short description |Control of jobs in a Unix shell}}
{{About |job control on a Unix-based system |the general computing term |job control (disambiguationcomputing){{!}}job control (computing)}}
In [[Unix]] and [[Unix-like]] [[operating system]]s, '''job control''' refers to control of '''jobs''' by a [[Unix shell|shell]], especially interactively, where a "job" is a shell's representation for a [[process group]]. Basic job control features are the suspending, resuming, or terminating of all processes in the job/process group; more advanced features can be performed by sending [[signal (computing)|signals]] to the job. Job control is of particular interest in Unix due to its [[multiprocessing]], and should be distinguished from [[job control block|job control]] generally, which is frequently applied to sequential execution ([[batch processing]]).
In a [[Unix]] or [[Unix-like]] [[operating system]], '''job control''' refers to controlling a [[process group]] as a [[job (computing)|job]] via a [[Unix shell| shell]].<ref>IEEE Std 1003.1-2001, [http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_201 Section 3.201, Job]</ref> Control features include suspend, resume, and terminate, and more advanced features can be performed by sending a [[signal (computing)|signal]] to a job. Job control allows a user to manage processing in the Unix-based [[multiprocessing]] environment, and is distinct from [[job control (computing)|general computing job control]].
 
==Overview==
When using [[Unix]] or [[Unix-like]] operating systems via a [[Computer terminal|terminal]] (or [[terminal emulator]]), a user will initially only have a single process running, their [[logging (computer security)|login]] [[Unix shell|shell]]. Most tasks{{efn|Here "task" is a non-technical term for "some activity", while "process" and "job" are technical terms.}} (directory listing, editing files, etc.) can easily be accomplished by letting the program take control of the terminal and returning control to the shell when the program exits – formally, by attaching to [[standard streams|standard input and standard output]] to the shell, which reads or writes from the terminal, and catching signals sent from the keyboard, like the termination signal resulting from pressing {{keypress|Control|C}}.
 
However, sometimes the user will wish to carry out a task while using the terminal for another purpose. A task that is running but is not receiving input from the terminal is said to be running "in the background", while the single task that is receiving input from the terminal is "in the foreground". Job control is a facility developed to make this possible, by allowing the user to start processes in the background, send already running processes into the background, bring [[background process]]es into the foreground, and suspend or terminate processes.
 
The concept of a ''job'' maps the (shell) concept of a single shell command to the (operating system) concept of the possibly many processes that the command entails. Multi-process tasks come about because processes may create additional child processes, and a single shell command may consist of a [[Pipeline (Unix)|pipeline]] of multiple communicating processes. For example, a command to select lines containing the text "title", sort these alphabetically, and display the result in a [[Terminal pager|pager]].
 
<syntaxhighlight lang="shell">
grep title somefile.txt | sort | less
</syntaxhighlight>
 
This creates at least three processes: one for {{mono|[[grep]]}}, one for {{mono|sort}}, and one for [[less (Unix)|{{mono|less}}]]. Job control allows the shell to control these related processes as one entity, and when a user issues the appropriate key combination (usually {{keypress|Control|Z}}), the entire group of processes gets suspended.
 
Jobs are managed by the operating system as a single [[process group]], and the job is the shell's internal representation of such a group. This is defined in [[POSIX]] as:<ref>IEEE Std 1003.1-2001, [http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_201 Section 3.201, Job]</ref>
 
{{blockquote|A set of processes, comprising a shell pipeline, and any processes descended from it, that are all in the same process group.}}
 
A job can be referred to by a [[Handle (computing)|handle]]{{efn|A job ID is an abstract reference by the shell to a resource (a process group) managed externally, by the operating system, hence is a handle.}} called the ''job control job ID'' or simply ''{{visible anchor|job ID}}'', which is used by [[shell builtin]]s to refer to the job. Job IDs begin with the <code>%</code> character; <code>%n</code> identifies job ''n'', while <code>%%</code> identifies the current job. Other job IDs are specified by [[POSIX]].<ref>IEEE Std 1003.1-2001, [http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_203 Section 3.203, Job Control Job ID]</ref> In informal usage the number may be referred to as the "job number" or "job ID", and Bash documentation refers to the (%-prefixed) job ID as the ''jobspec.''<ref>[https://www.gnu.org/software/bash/manual/html_node/Job-Control-Basics.html#Job-Control-Basics 7.1 Job Control Basics]</ref>
 
Job control and job IDs are typically only used in interactive use, where they simplify referring to process groups; in scripting PGIDs are used instead, as they are more precise and robust, and indeed job control is disabled by default in bash scripts.
 
==History==
Job control was first implemented in the [[C shell]] by Jim Kulp,<ref>
Foreword by [[Bill Joy]] in {{cite book
Line 38 ⟶ 17:
}}
</ref> then at [[IIASA]] in Austria, making use of features of the 4.1[[BSD]] kernel.
The [[KornShell]], developed at [[Bell Labs]], adopted it and it was later incorporated into the SVR4 version of the [[Bourne shell]], and exists in most modern Unix shells.
 
==CommandsJob==
A job encompasses all of the processes that start for the handling of a shell [[command line]]. A simple command line may start just one process, but a command line may result in multiple processes since a process can create [[child process]]es, and a command line can specify a [[Pipeline (Unix)|pipeline]] of multiple commands. For example, the following command line selects lines containing the text "title", sorts them alphabetically, and displays the result in a [[terminal pager]]: <code>grep title somefile.txt | sort | less</code>. This creates at least three processes: one for [[grep|{{code |grep}}]], one for {{code |sort}}, and one for [[less (Unix)|{{code |less}}]]. Job control allows the shell to control these processes as one entity.
The POSIX standard specifies two commands for resuming suspended jobs in the background and foreground, respectively {{mono|bg}} and {{mono|fg}}. These were modeled after the Korn shell job control commands.<ref>{{man|cu|bg|SUS}}; {{man|cu|fg|SUS}}.</ref>
 
==Job ID{{anchor |job ID}}==
==Implementation==
A job canis beidentified referredby toa bynumeric ''job ID'', a.k.a. ''job number'' which is classified as a [[Handle (computing)|handle]]{{efn|A jobsince IDit is an abstract reference by the shell to a [[computer resource |resource]] (a process group). managedAn externally,ID by the operating systemvalue, henceprefixed iswith a handle.}} called the ''job control job ID'' or simply ''{{visible anchorcode|job ID%}}'', whichcan isbe used bywith [[shella builtin]]sjob tocontrol refercommand to thespecify a job. JobThe IDsspecial beginreferences with the <{{code>|%%</code>}} character;and <{{code>|%n</code>+}} identifiesrefer jobto ''n'',the whiledefault <code>%%</code> identifiesjob; the currentone job.that Otherwould jobbe selected IDsif arenone specified by [[POSIX]].<ref>IEEE Std 1003.1-2001, [http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_203 Section 3.203, Job Control Job ID]</ref> In informal usage the number may be referred to as the "job number" or "job ID", and Bash documentation refers to thea reference (starting with {{code|%-prefixed}}) job ID as thea ''jobspec.'' (short for job specification).<ref>[https://www.gnu.org/software/bash/manual/html_node/Job-Control-Basics.html#Job-Control-Basics 7.1 Job Control Basics]</ref>
 
Job control and jobID IDsvalues are typically only used in an interactive use,shell. whereIn theyscripting, simplify referring to process groups; in scriptingPGID PGIDsvalues are used instead, as they are more precise and robust, and indeed job control is disabled by default in a bash scriptsscript.
 
==Foreground/background==
By default, a job runs in the foreground where it uses [[standard streams |interactive input and output]]. The user enters a command line and interacts with the processes but cannot issue another command until the current job terminates. Many operations (i.e. listing files) are relatively quick so the user can wait for a response with little down time and some operations (i.e. editing) require interaction that is only possible via a foreground job. But, if interaction is not required and the operation prevents access to the shell for a long time, the user may want to run it in the background {{endash}} where the processes cannot access interactive input but the user can perform other foreground operations while the background job runs concurrently. By default background jobs output to the interactive output stream which results in the interleaving of output from the foreground and background jobs although a user may [[Redirection (computing)|redirect]] output for a background job to prevent this.
 
==Control==
[[POSIX]] specifies the [[user interface]] to job control {{endash}} modeled on the Korn shell.<ref>{{man|cu|bg|SUS}}; {{man|cu|fg|SUS}}.</ref>. The commands are typically implemented as [[shell builtin]]s; not separate [[computer program |programs]].
 
; Start in background
:If a command line ends with {{code|&}}, then the job starts in the background.
; Pause foreground job
:The foreground job can be paused by pressing {{keypress |Ctrl| Z}}. In this state, a job can be resumed in the background via {{code |bg}} or resumed in the foreground via {{code |fg}}.
; Command {{code |fg}} {{anchor| fg}}
:Command {{code |fg}} (short for foreground) moves background job to the foreground; either the job specified or the one most recently added to the background if none specified. When the foreground job is paused (via {{keypress |Ctrl| Z}}), then this command resumes that job.
; Command {{code |wait}}
:Command [[wait (command)|<code>wait</code>]] pauses the interactive session until the specified background jobs complete or for all background jobs of the active shell if none specified.<ref>{{cite web | last=Kerrisk| first=Michael |date=Feb 2, 2025 |title=wait(1p) — Linux manual page |website=man7.org |url=https://www.man7.org/linux/man-pages/man1/wait.1p.html |publisher= |access-date=May 13, 2025}}</ref>
; Command {{code |bg}} {{anchor| bg}}
:Command {{code |bg}} (short for background) moves the paused foreground job to the background and resumes it.
; Command {{code |jobs}}
:Command {{code |jobs}} reports information about each background job including ID, command line and running status (stopped or running).
 
==Signals==
{{Unreferenced section|date=February 2020}}
The [[interprocess communication]] of job control is implemented via [[Unix signal |signal]]s.
Typically, the shell keeps a list of jobs in a '''job table'''. Recall that a job corresponds to a process group, which consists of all the members of a [[pipeline (Unix)|pipeline]] and their descendants. The <code>jobs</code> command will list the background jobs existing in the job table, along with their job number and job state (stopped or running). When a [[login session|session]] ends when the user [[logout|logs out]] (exits the shell, which terminates the ''session leader'' process), the shell process sends [[SIGHUP]] to all jobs, and waits for the process groups to end before terminating itself.
 
Typically, a shell maintains information about background jobs in a job table. When an [[login session |interactive session]] ends (i.e. user [[logout |logs out]]), the shell sends signal [[SIGHUP]] to all jobs, and waits for the process groups to exit before terminating itself. Some shells provide a non-POSIX command [[Disown (Unix)|<code>disown</code>]] that removes a job from the job table. The process group becomes an [[orphan process |orphan]]. The shell will not send it SIGHUP, nor wait for it to terminate. This is one technique for enabling a process as a [[daemon (computer software)|daemon]]; owned direclty by the root process [[init]]. The POSIX command [[nohup |{{code |nohup}}]] provides an alternate way to prevent a job from being terminated by the shell.
The [[Disown (Unix)|<code>disown</code>]] command can be used to remove jobs from the job table, so that when the session ends the child process groups are not sent SIGHUP, nor does the shell wait for them to terminate. They thus become [[orphan process]]es, and may be terminated by the operating system, though more often this is used so the processes are adopted by [[init]] (the kernel sets their parent process to init) and continue executing as [[daemon (computer software)|daemon]]s. Alternatives to prevent jobs from being terminated include [[nohup]] and using a [[terminal multiplexer]].
 
A job running inSuspending the foreground canjob be(via stopped{{keypress by|Ctrl typing the suspend character ([[Ctrl-|Z]]}}). This sends thesignal "SIGTSTP (terminal stop") to [[signalthe (computing)|signal]]processes ('''SIGTSTP''') toof the process group. By default, SIGTSTPthis signal causes processesa receiving itprocess to stop,pause andso controlthat isthe returnedshell tocan the shellresume. However, a process can registerignore athe signal handler for or ignore SIGTSTP. A process can also be paused withvia thesignal "stop" signalSIGSTOP ('''SIGSTOP'''stop), which cannot be caught or ignored.
 
A job running inWhen the foregrounduser canpresses be{{keypress interrupted|Ctrl by typing|C}}, the interruption character ([[Ctrl-C]]). Thisshell sends the "interrupt" signal ('''[[SIGINT (POSIX)|SIGINT]]''' (interrupt) to each foreground job process, which defaults to terminating the processit, though ita process can beignore overriddenthe signal.
 
When a stopped job is resumed (via {{code |bg}} or {{code |fg}}), the shell redirects [[Input/output]] and resumes it by sending signal SIGCONT to it.
A stopped job can be resumed as a background job with the <code>[[bg (Unix)|bg]]</code> [[shell builtin|builtin]], or as the foreground job with <code>[[fg (Unix)|fg]]</code>. In either case, the shell redirects [[Input/output|I/O]] appropriately, and sends the '''SIGCONT''' signal to the process, which causes the operating system to resume its execution. In [[Bash (Unix shell)|Bash]], a program can be started as a background job by appending an ampersand (<code>&</code>) to the command line; its output is directed to the terminal (potentially interleaved with other programs' output), but it cannot read from the terminal input.
 
A background process that attempts to read from or write to its [[controlling terminal]] is sent asignal '''SIGTTIN''' (for input) or '''SIGTTOU''' (for output) signal. These signals stop the process by default, but they may also be handled in other ways. Shells often override the default stop action of SIGTTOU so that background processes deliver their output to the controlling terminal by default.
 
In Bash-compatible shells, the <code>[[kill (command)|kill]]</code> builtin (not <code>/bin/kill</code>) can signal jobs by job ID as well as by process group ID – sending a signal to a job sends it to the whole process group, and jobs specified by a job ID should be killed by prefixing <code>%</code>. <code>kill</code> can send any signal to a job; however, if the intent is to rid the system of the processes the signals [[SIGKILL]] and [[SIGTERM]] (the default) are probably the most applicable.
 
In Bash-compatible shellsbash, the <code>[[kill (command)|kill]]</code> builtin (not <code>/bin/kill</code>) can signal jobs by job ID as well as by process group ID. – sendingSending a signal to a job sends it to the wholeeach process group,of andthe jobs specified by a job ID should be killed by prefixing <code>%</code>group. <code>kill</code> can send any signal to a job; however, if the intent is to rid the system of the processes, the signals [[SIGKILL]] and [[SIGTERM]] (the default) are probably the most applicable.
<!--
==See also==
* [[C shell]]
 
==Notes==
{{Notelist}}
-->
 
==References==
Line 75 ⟶ 77:
date=2004-08-02|
publisher=Addison Wesley|
chapterurlchapter-url=http://www.informit.com/articles/article.aspx?p=366888&seqNum=8|
chapter=FreeBSD Process Management: Process Groups and Sessions|
isbn=0-201-70245-2}}