Processes and jobs · bash builtin
fg
Bring a background or stopped job into the foreground, so it gets the terminal and the shell waits for it.
fg [JOBSPEC]
fg is half of the interactive job-control pair with bg. The everyday move: you are in
vim or less, press Ctrl-Z, the shell prints [1]+ Stopped vim notes.txt and gives you
a prompt; you run a command or two, then type fg and you are back in the editor exactly where
you were. Ctrl-Z sends the TSTP signal, which stops the foreground job; fg sends CONT and
hands it the terminal again, and the shell waits until it finishes or is stopped again.
Without an argument fg picks the current job, marked + in jobs. Give %2, %vim or
%?notes to choose another. With several stopped editors, jobs then fg %N is the usual
routine.
fg needs job control, which interactive shells have and scripts do not. In a script (and in
these examples, which run under bash -c) fg fails with no job control unless the script
runs set -m first. With set -m it works: it resumes the job if stopped and waits for it,
returning its exit status. The examples cannot press Ctrl-Z or give a job a terminal, so they
stop jobs with kill -TSTP, the same signal.
Examples
fg in a script without job control
sleep 1 &
fg
/bin/bash: line 2: fg: no job control
Non-interactive shells start with job control off, so fg refuses with no job control and
exit status 1. In a script you almost always want wait instead.
Resume a stopped job in the foreground
set -m
(sleep 1; echo "job finished") &
kill -TSTP %1
sleep 0.1
jobs
fg %1
echo "fg returned $?"
[1]+ Stopped ( sleep 1; echo "job finished" ) ( sleep 1; echo "job finished" ) job finished fg returned 0
set -m turns job control on. kill -TSTP stops the job as Ctrl-Z would; jobs shows it
Stopped. fg prints the job's command, resumes it and waits; the job completes and fg
returns its exit status.
fg returns the job's exit status
set -m
(sleep 0.5; exit 7) &
fg
echo "fg returned $?"
( sleep 0.5; exit 7 ) fg returned 7
With no argument fg takes the current job. Like wait, it returns the job's own exit
status (7 here), so fg && echo ok reacts to whether the job succeeded.
Choose a job by name
set -m
sleep 0.5 &
(sleep 0.2; echo "second job done") &
sleep 0.1
fg %sleep
jobs
sleep 0.5 second job done [2] Done ( sleep 0.2; echo "second job done" )
%sleep selects the job whose command starts with sleep, even though it is not the
current job. fg waits for it; jobs then reports the other job, which finished in the
meantime, as Done.
No job to bring back
set -m
fg
/bin/bash: line 2: fg: current: no such job
With an empty job table there is no current job: current: no such job, exit status 1.
Common pitfalls
Pressing Ctrl-Z and forgetting the job. Stopped jobs use no CPU but keep their memory, open files and locks. bash warns
There are stopped jobson the firstexit; a secondexitkills them.Expecting
fgto work in a script or inssh host 'cmd'without a terminal. Without job control it fails; usewaitto wait for background work.Using
fgto wait for a job in aset -mscript when its output or input matters:fggives the job the terminal, which in a script is usually not what you want.wait %1is clearer.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
fgandbgare shell builtins, specified by POSIX for shells with job control; they work the same in bash, zsh, ksh and dash on Linux and macOS. The%nameand%?textjob specs are supported by all of them.
Related
bgResume a stopped job in the background, as if it had been started with &.jobsList the background and stopped jobs of the current shell, with their job numbers and state.waitWait for background jobs of the current shell to finish, and return their exit status.killSend a signal to processes by PID or job number; by default TERM, which asks a process to exit.nohupRun a command immune to the hangup signal, so it keeps running after you log out or close the terminal.- Subshells and command groupingThe difference between ( ... ) and { ...; }, what a subshell inherits and what it cannot change, which constructs create one, and what that costs.