Topic 3.3
Foreground, Background & Job Control
In one line
A command can run in the FOREGROUND (blocking your terminal until it finishes) or the BACKGROUND (freeing your terminal immediately) — and a handful of commands let you move between the two.
Think of it like this
Talking on the phone (foreground — you can't do anything else until the call ends) versus starting a load of laundry and walking away (background — it runs on its own while you do other things, and you can check on it whenever you like).
Key ideas
- 01
By default, any command you run occupies the FOREGROUND — your terminal is blocked, showing no prompt, until it finishes. Appending
&runs it in the BACKGROUND instead, returning your prompt immediately while the command keeps running. - 02
jobslists every background/suspended job started from your CURRENT shell session (with a job number like[1]).fg %1brings job 1 back to the FOREGROUND;bg %1resumes a suspended job IN the background. Ctrl+Z suspends (pauses) whatever's currently in the foreground without killing it, handing control back to your prompt immediately. - 03
A background job is still tied to your terminal SESSION by default — closing that terminal (or losing an SSH connection) normally sends SIGHUP to every job started from it, terminating them too.
nohup <command> &explicitly ignores that hangup signal, letting the command keep running even after you disconnect entirely. - 04
disownremoves a job from your shell's job table without killing it, so it survives your terminal closing even if you forgot tonohupit upfront — a genuinely useful 'oh, I should have backgrounded this properly' rescue move for something already running. - 05
For anything genuinely long-running that needs to survive disconnection reliably,
tmuxorscreen(terminal MULTIPLEXERS) are the more robust modern answer — they create a persistent session you can detach from and reattach to later from anywhere, rather than relying onnohupalone.
Code & diagrams
Practice with a harmless long-running sleep — safe to experiment freely.
# Start something in the background
sleep 300 &
jobs
# [1]+ Running sleep 300 &
# Bring it to the foreground
fg %1
# (now blocked — press Ctrl+Z to suspend it)
# ^Z
# [1]+ Stopped sleep 300
# Resume it in the background again
bg %1
jobs
# [1]+ Running sleep 300 &
# Survive disconnection: nohup + &
nohup sleep 300 > /dev/null 2>&1 &
disown
# Confirm it's no longer tied to this shell's job table
jobs # (should no longer list it)Explain it without notes
Why does closing your terminal normally kill every background job you started from it, and how does nohup change that?
What's the practical difference between Ctrl+Z (suspending a job) and Ctrl+C (which most people already know terminates one)?
Practice
Start a long sleep in the foreground, suspend it with Ctrl+Z, resume it in the background with bg, then bring it back to the foreground with fg and let it finish or Ctrl+C it.
Start a background job with nohup, confirm it survives by checking jobs shows nothing tied to your shell after disown, then find it independently with ps to confirm it's still actually running.
Trade-offs
- ↔
nohup/disownare lightweight and need no extra tooling, but they don't automatically restart a crashed process or manage its logs well — for anything you actually depend on staying up, a real process supervisor (systemd, next topic, or something like PM2) is worth the small extra setup cost over ad-hoc nohup usage.
Done when you can
I can move a job between foreground and background using fg, bg, and Ctrl+Z.
I understand why a background job dies when its terminal closes, and how nohup prevents that.
I know Ctrl+C terminates while Ctrl+Z suspends — a genuinely different, reversible action.