Background and Foreground: &, jobs, fg, nohup
Sometimes you start a command and realize it’ll take an hour. Sometimes you SSH in, start a server, and the moment you log out it dies. Bash gives you precise control over which processes run in the foreground (blocking your terminal) versus the background (released back to the prompt) — and how to survive a disconnect.
Run a command in the background
Append &:
./long-task.sh &
# [1] 12345 ← job number 1, PID 12345
# back to prompt immediately
Output (stdout/stderr) still goes to your terminal — usually messy. Redirect it:
./long-task.sh > task.log 2>&1 &
See your jobs
jobs # list jobs in current shell
jobs -l # also show PIDs
jobs -p # only PIDs
Foreground / background a running job
fg # bring most recent background job to foreground
fg %1 # bring job number 1 to foreground
bg # resume most recent stopped job in background
bg %2 # resume job 2 in background
Suspend a foreground command
While a command is running in the foreground:
Ctrl+Z # suspend (process is stopped, not killed)
Then push it to background:
bg # continue it in background
fg # bring it back to foreground
Common workflow: start vim, hit Ctrl+Z, do something in shell, type fg to go back to vim where you left off.
Survive a disconnect
If you SSH in and run something, then disconnect, your shell process gets a SIGHUP — which kills your background jobs by default. Three ways to survive:
nohup
nohup ./long-task.sh &
# output goes to nohup.out unless you redirect
The nohup command makes the process ignore SIGHUP. It will keep running after logout.
disown (after the fact)
Started a job and forgot to nohup it? Disown after the fact:
./long-task.sh &
disown # detach from current shell
tmux or screen (the real answer)
The proper tool for “I want to run something on a server and reconnect later” is tmux (or the older screen). It’s a terminal multiplexer — your sessions live independently of any SSH connection.
# start a named session
tmux new -s mywork
# do whatever you want; everything keeps running
# detach: press Ctrl+b then d
# you're back in your shell, but tmux is still running
# reconnect anytime — even from a different machine
tmux attach -t mywork
# list sessions
tmux ls
tmux is the answer to “I started something on a server and want to come back to it tomorrow.”
Kill background jobs
kill %1 # kill job 1
kill -9 %1 # force kill
kill 12345 # kill by PID
killall firefox # kill all processes named firefox
Common patterns
# Run a build in background, log everything
make all > build.log 2>&1 &
# Wait for ALL background jobs to finish
./job1 &
./job2 &
./job3 &
wait
echo "all done"
# Run a long thing on a server and keep it running
ssh server
tmux
./long-task.sh
# Ctrl+b d to detach
exit # SSH session ends; tmux session keeps running
# Reconnect later
ssh server
tmux attach
Common mistakes
- Forgetting to redirect output — your background job spams the terminal.
- Using
nohupwhen you should usetmux— for anything interactive, tmux is better. fgwith no jobs — “bash: fg: current: no such job”.- Closing the terminal with running foreground processes — they all die. Suspend with Ctrl+Z + bg + disown first, or use tmux.
What to learn next
Background processes get sent signals (SIGHUP, SIGTERM, SIGKILL) when you kill them. Understanding signals — what each one does and which to use — is the next topic.