Chapter 32 — Job control: foreground, background, and nohup
In one sentence
A shell can run commands in the foreground (you wait for it) or the background (it runs while you keep typing), and understanding exactly what happens to a background job when your terminal session ends is the difference between a smooth long-running task and a lost one.
Why this matters
Starting a multi-hour data migration over SSH, then having your connection drop and the job silently die with it, is one of the most common, most avoidable real production frustrations — and it's entirely explained by Chapter 20's signals.
How it actually works
command & # run in the BACKGROUND -- your shell keeps
# control immediately, doesn't wait
jobs # list your shell's current background/stopped
# jobs
fg %1 # bring job 1 to the FOREGROUND (wait for it)
bg %1 # resume a STOPPED job in the background
Ctrl-Z # SUSPEND (STOP, Chapter 5's `T` state) the
# current foreground job
Ctrl-C # send SIGINT to the current foreground job
# (Chapter 20)
nohup command & # run in the background, AND ignore SIGHUP --
# so it survives your terminal/SSH session
# ending
disown %1 # remove a job from your shell's job table
# WITHOUT killing it -- it keeps running, but
# your shell stops tracking it
Why a background job can still die when you log out: when your SSH
session (or terminal) closes, the shell process itself is typically sent
SIGHUP ("hang up" — a name dating back to actual telephone modems). By
default, many programs' handling of SIGHUP (or simply inheriting the shell's
own death) means background jobs started with a plain & can be killed too,
unless something protects them — which is exactly nohup's job.
Real-world example
"I started a long-running migration/backup/build over SSH, my
connection dropped, and the job died with it" is one of the single
most common, most universally-experienced real frustrations in
day-to-day Linux/ops work -- documented in essentially every "Linux
tips" resource and endlessly rediscovered by engineers the hard way,
usually mid-incident, at the worst possible time. The mechanism is
exactly this chapter's: the SSH session closing sends SIGHUP toward
the shell and, often, its children; a plain background job (`&` with
no protection) can die right along with it.
THE REAL, PRACTICAL FIXES, all addressing the same root cause:
`nohup long_command &` explicitly ignore SIGHUP
`disown` detach an ALREADY-running job from
the shell's job table
`screen` / `tmux` (properly) run the command inside a
TERMINAL MULTIPLEXER session that
keeps running independently of your
SSH connection entirely -- you can
disconnect and RE-ATTACH later, seeing
the still-running session exactly as
you left it. This is the tool most
experienced engineers actually reach
for by default for anything long-
running, precisely because it survives
network drops, not just deliberate
logouts.
Try it yourself
# See job control directly
sleep 100 &
jobs # shows [1]+ Running sleep 100 &
fg # brings it to foreground -- now press Ctrl-C
# to actually stop it (or wait, or Ctrl-Z)
sleep 100 &
kill -STOP %1 # simulate Ctrl-Z from a script
jobs # shows Stopped
bg %1 # resume it in the background
jobs # now Running again
kill %1 # clean up
# See nohup protect a job from SIGHUP (simulated, safely)
nohup sleep 60 > /tmp/nohup_test.log 2>&1 &
echo "PID $! is protected from SIGHUP"
kill $! # clean up
# If tmux is installed, try it
tmux new -s demo 'echo "inside tmux"; sleep 5; echo done' 2>/dev/null || \
echo "(tmux not installed -- worth adding for real long-running work)"
Common mistakes
- Assuming
&alone is enough for a job that must survive logout. It isn't, by default — pair it withnohup,disown, or better, run it insidescreen/tmuxfrom the start. - Forgetting
fg/bgneed a job NUMBER (%1) if you have more than one. With only one background job, plainfg/bgworks; with several, you need to specify which. - Starting a critical long-running task directly over a plain SSH session
"because it'll probably be fine." For anything that takes more than a
few minutes, use
tmux/screenas a default habit, not an afterthought.
Check yourself
- What signal typically threatens a background job when your SSH session closes, and why?
- What does
nohupactually do? - Why do experienced engineers often prefer
tmux/screenovernohupfor long-running work?
Further reading
- Reference:
man 1 nohup,man 1 jobs,man 1 disown,man 1 tmux. - Book (free): The Linux Command Line — the job-control chapter covers this cleanly with worked examples.
- Guide: any good
tmuxcheat sheet — worth genuinely learning, not just skimming, given how often it pays off.