Table of Contents
Understanding Jobs vs Processes (Quick Recap)
A process is a running program.
A job is your shell’s way of tracking processes you started from that shell.
This chapter is about how your shell (typically Bash) lets you run those jobs in the foreground or background and control them interactively.
Key idea:
- Foreground job: Owns the terminal. You interact with it directly; other commands wait.
- Background job: Runs “behind the scenes” while your shell prompt is still available.
Running Commands in the Foreground
By default, when you type a command and press Enter, it runs in the foreground:
- The terminal is “busy” with that process.
- Keyboard input (like typing) goes to that process.
- Signals from the keyboard (like
Ctrl+C) go to that process.
Example:
sleep 30
The prompt will not return until sleep finishes (30 seconds) or you interrupt it.
Foreground usage is best when:
- You need to interact with the program (shells, editors, REPLs, etc.).
- You expect it to finish quickly.
Starting Jobs in the Background
To start a job directly in the background, add & at the end:
sleep 300 &What happens:
- The shell prints a job ID and a PID (process ID), for example:
[1] 12345[1]– job number (used with job-control commands)12345– actual system process ID
- The shell returns immediately to the prompt.
- The command keeps running in the background.
Use background jobs when:
- A command takes a long time (backup, long computation, download).
- You don’t need to interact with it via the terminal.
You can run multiple background jobs:
sleep 100 &
sleep 200 &
Each gets its own job number: [1], [2], etc.
Listing Jobs
Use jobs (a shell built-in) to see what your current shell is tracking:
jobsTypical output:
[1]- Running sleep 300 &
[2]+ Running sleep 200 &Meaning:
[1]/[2]– job numbers.Running/Stopped– job state.+– current job (default target for%+or many job-control commands).-– previous job.
jobs only shows jobs started from the current shell session, not every process on the system.
Useful variants:
jobs -l– also shows PIDs.
jobs -l
[1]- 12345 Running sleep 300 &
[2]+ 12346 Running sleep 200 &Suspending Foreground Jobs (`Ctrl+Z`)
You can suspend (pause) a running foreground job using:
Ctrl+Z
This sends a SIGTSTP signal, causing the job to stop temporarily.
Example:
- Run:
sleep 300- Press
Ctrl+Z:
^Z
[1]+ Stopped sleep 300Now:
- The job is stopped, not running.
- The shell prompt comes back.
- The job appears in
jobswithStoppedstatus.
Why suspend? To:
- Free the terminal while keeping the job in memory.
- Decide later whether to resume it in the foreground or background.
Moving Jobs to the Background (`bg`)
After suspending a job, you can resume it in the background with bg.
Basic usage (most common):
bgResumes the most recent stopped job.
Example:
sleep 300
^Z
[1]+ Stopped sleep 300
bg
[1]+ sleep 300 &
Now sleep 300 runs in the background.
To specify a particular job:
bg %1
bg %2%1refers to job[1].%2refers to job[2].
You can see the effect with:
jobs
bg only works on stopped jobs, not already-running background jobs.
Bringing Jobs to the Foreground (`fg`)
To bring a job to the foreground (so it owns the terminal again), use fg.
Most common:
fg
Brings the current job (+) to the foreground.
Example:
sleep 300 &
# Do something else...
fgMore precise:
fg %1
fg %2Useful patterns:
- Background a long-running job, then later
fgit when you want to see its output or stop it. - Suspend (
Ctrl+Z) a misbehaving app, think about it, thenfgto interact with it again.
While a job is in the foreground:
Ctrl+C– usually terminates it.Ctrl+Z– suspends it again.
Job Identifiers: `%` Syntax
Job-control commands (fg, bg, kill in job-control context) often take job IDs prefixed with % instead of PIDs.
Common forms:
%1– job with number 1.%+– current job (same as justfgorbgwith no args).%-– previous job.%sleep– job whose command starts withsleep.%?pattern– job whose command line containspattern.
Examples:
jobs
[1]- Running long_task &
[2]+ Stopped nano notes.txt
fg %+ # bring 'nano notes.txt' to foreground
bg %- # background the previous job
fg %long # if 'long_task' is uniqueThis is convenient when PIDs are long or you remember the command but not the number.
Stopping and Killing Background Jobs
Even though full process management is another chapter, it’s common to control jobs with kill using job IDs.
Kill using a job ID:
kill %1 # send SIGTERM to job [1]
kill -9 %1 # force kill job [1] (SIGKILL)You can also:
- Bring a job to the foreground with
fgand then pressCtrl+Cto terminate it normally.
After a job finishes or is killed, you may see a message sometime later:
[1]+ Done sleep 300
Or via jobs:
jobs
[1]+ Done sleep 300
Once it’s marked Done, the shell forgets it after the next prompt or command.
Background Jobs and Terminal Output/Input
Important behavior differences:
- Input:
- Foreground jobs read from the terminal by default.
- Background jobs generally should not read from the terminal.
- If a background job tries to read from the terminal, you may see:
[1]+ Stopped (tty input) command
The job stops until you bring it to the foreground with fg.
- Output:
- Background jobs can write to the terminal.
- Their output may appear intermixed with your shell commands and other programs.
- To avoid clutter, use redirection:
long_command > output.log 2>&1 &
This sends both standard output and error to output.log.
Long-Running Jobs and Session Lifetime (`nohup`, `disown`)
By default, when you close the terminal (or log out):
- The shell sends a
SIGHUP(“hangup”) to its jobs. - Many foreground and background jobs terminate.
Two common tools to keep jobs alive after logout (detailed behavior is learned later, but you should recognize them):
nohup– run a command immune to hangups:
nohup long_command > output.log 2>&1 &- Output is preserved (default to
nohup.outif not redirected).
disown(Bash, Zsh) – remove jobs from the shell’s control:
long_command &
disown %1
The job keeps running even if the shell exits, and it no longer appears in jobs.
These are especially useful when you accidentally start a long task interactively and need to disconnect.
Practical Usage Patterns
Here are common “job control workflows” you’ll likely use often:
1. Temporarily “Parking” a Foreground Task
# You’re in nano editing a config file…
Ctrl+Z # suspend nano
jobs # confirm it's 'Stopped'
bg # resume nano in background (dangerous if it needs input)
fg # bring nano back when ready
More realistically, editors prefer the foreground; use Ctrl+Z mainly for long-running, non-interactive jobs.
2. Freeing the Terminal While Something Runs
long_script.sh # you forgot to start it in background
Ctrl+Z # suspend
bg # resume in background
jobs # check status3. Managing Multiple Long Tasks
backup.sh &
log_analysis.sh &
jobs # see which job is which
fg %1 # watch backup progress
Ctrl+Z # suspend when bored
bg %1 # let backup continue in background
fg %2 # check on log_analysis4. Cleanly Stopping a Background Job
jobs
[1]- Running backup.sh &
[2]+ Running monitor.sh &
kill %1 # ask backup.sh to stop (SIGTERM)
jobs
[1]- Terminated backup.shOr:
fg %2
Ctrl+C # interrupt in the foregroundLimitations and Notes
- Job control is a shell feature:
- Available in interactive shells like Bash.
- Not available in very minimal shells or in some non-interactive scripts (depending on settings).
jobs,fg,bg,disownare usually built-ins, not standalone executables:- They affect jobs only in the current shell.
- Different terminals (and remote connections via SSH) each have their own independent set of jobs.
Understanding foreground and background jobs gives you much finer control over your interactive sessions, letting you multitask effectively from the command line.