| |

LFCS 57 ๐Ÿง Background Jobs โ€” &, bg, fg, jobs

โฑ๏ธ Estimated read: 11 min | |

A shell session is not limited to running one command at a time. Job control is the mechanism that lets you start a process in the background, suspend a foreground process, resume it later, and list everything the shell is managing. The ampersand (&) starts a command asynchronously, returning the prompt immediately while the process runs in the background. Ctrl+Z suspends the foreground process and returns control to the shell. bg resumes a suspended job in the background, fg brings it back to the foreground, and jobs lists every job the shell is tracking . The LFCS exam expects you to know all four, because “manage or schedule jobs for executing commands” is an explicit objective in the Operations Deployment domain .

The distinction between a job and a process is the first thing to internalize. A job is a shell-level abstraction: it is a pipeline, and all the processes in that pipeline belong to the same job. The shell assigns each job a job number (starting at 1), and that number is how you refer to it with %1, %2, and so on . The jobs command lists the jobs, fg %1 brings job 1 to the foreground, and bg %1 resumes it in the background. The process ID is a separate identifier, and jobs -l shows both.

Key point: command & starts a job in the background. Ctrl+Z suspends the foreground job. bg %n resumes a suspended job in the background, fg %n resumes it in the foreground, and jobs lists the shell’s jobs. A background job cannot read from the terminal; if it tries, the terminal driver sends SIGTTIN and suspends it .


Why job control exists

The terminal ownership problem. A terminal can have exactly one foreground process group at a time. That group receives the keyboard-generated signals (SIGINT from Ctrl+C, SIGTSTP from Ctrl+Z) and has read/write access to the terminal. Background processes are in a different process group, so they are immune to those signals, but they are also denied read access: if a background process tries to read from the terminal, the driver sends SIGTTIN, which suspends it unless the process catches the signal . This is why vim & does not workโ€”vim needs terminal input, and the shell suspends it immediately.

The long-running task problem. A compile, a download, or a database dump can take minutes or hours. Running it in the foreground blocks the shell, and the user cannot run any other command. The & operator returns the prompt immediately and prints a line like [1] 25647, where 1 is the job number and 25647 is the PID of the last process in the pipeline . The shell continues to track the job, and jobs shows its status.

The interruption problem. Sometimes a task is already running in the foreground and you realize you need the shell backโ€”to check a log, to answer a question from a colleague, to start another command. Ctrl+Z sends SIGTSTP to the foreground process group, which stops the processes and returns control to the shell . The job is now in the “Stopped” state. bg resumes it in the background, fg resumes it in the foreground.

The job reference problem. A shell session can have many jobs. The job number is the short identifier, but the shell also supports references by command prefix: %ce refers to the stopped ce job, and %?ce refers to any job containing ce in its command line. The current job is %% or %+, and the previous job is %- . The + and - flags in the jobs output identify the current and previous jobs.


a. Starting a background job with &

The ampersand at the end of a command starts it asynchronously. The shell forks, the child runs the command, and the parent returns the prompt. The shell prints the job number and the PID.

# Start a long-running command in the background
# The & at the end makes it asynchronous
# The shell prints the job number and PID
sleep 300 &

# Output: [1] 12345
# [1] is the job number
# 12345 is the PID

# The prompt returns immediately
# The sleep process runs in the background

# Start a pipeline in the background
# The whole pipeline is one job
# The PID is the last process in the pipeline
find / -name "*.log" 2>/dev/null | gzip > logs.gz &

# Output: [2] 12346

The job number is assigned in sequence. The first background job is [1], the second is [2], and so on. The PID is the process ID of the last command in the pipeline, not the first . For a single command, they are the same. For a pipeline, the shell tracks the job by the pipeline as a whole, and the jobs command shows the job number and the status.

The background job’s output still goes to the terminal unless it is redirected. A background job that writes to stdout will interleave its output with the shell prompt. The standard practice is to redirect the output to a file or to /dev/null .


b. Suspending and resuming with Ctrl+Z, bg, and fg

Ctrl+Z suspends the foreground job. The process is stopped, not killed; it can be resumed. The shell prints a line like [1]+ Stopped sleep 300 and returns the prompt.

# Run a command in the foreground
sleep 300

# Press Ctrl+Z
# The shell suspends the sleep process
# Output: [1]+ Stopped sleep 300

# The prompt returns
# The job is in the Stopped state

# Resume the job in the background
bg %1

# Output: [1]+ sleep 300 &
# The process is now running in the background

# Bring the job back to the foreground
fg %1

# The shell is now waiting for the sleep to finish
# Press Ctrl+C to interrupt it

The bg command resumes a suspended job as if it had been started with & . If the job is already running in the background, bg has no effect and returns success. The fg command resumes the job in the foreground and makes it the current job . If the job is running in the background, fg moves it to the foreground, which means it regains terminal access and becomes subject to Ctrl+C and Ctrl+Z.

The job specification is optional. fg with no argument resumes the current job, which is the one marked with + in the jobs output. bg with no argument does the same. The %1 form is the explicit reference, and %1 & is a synonym for bg %1 .


c. Listing and managing jobs with jobs

The jobs command lists the shell’s jobs. The output shows the job number, the state (Running, Stopped), and the command line.

# Start two background jobs
sleep 100 &
# Output: [1] 12347

sleep 200 &
# Output: [2] 12348

# List the jobs
jobs

# Output:
# [1]-  Running                 sleep 100 &
# [2]+  Running                 sleep 200 &

# The + marks the current job
# The - marks the previous job

# List with PIDs
jobs -l

# Output:
# [1]- 12347 Running             sleep 100 &
# [2]+ 12348 Running             sleep 200 &

# List only running jobs
jobs -r

# List only stopped jobs
jobs -s

The -l flag adds the PID to the output. The -r and -s flags filter by state: -r shows only running jobs, and -s shows only stopped jobs . The -n flag shows only jobs whose status has changed since the last notification, which is useful in a script that polls for completion.

The + and - markers are not decoration. The + job is the current job, and fg or bg with no argument operates on it. The - job is the previous job, and %- refers to it. When the current job is terminated, the - job becomes the current job.

The kill command works with job specifications as well as PIDs. kill %1 sends SIGTERM to the job’s process group, which terminates the whole pipeline . The %1 form is the job reference, and the shell translates it to the process group ID.


Complete Example Session

The following session starts a background job, suspends a foreground job, resumes it in the background, lists the jobs, and brings one back to the foreground.

# ============================================
# PART 1: START A BACKGROUND JOB
# ============================================
# The sleep runs in the background
# The shell prints the job number and PID
sleep 300 &
# Output: [1] 12345

# ============================================
# PART 2: START A FOREGROUND JOB AND SUSPEND IT
# ============================================
# Run a foreground command
top

# Press Ctrl+Z
# The top process is suspended
# Output: [2]+ Stopped top

# ============================================
# PART 3: LIST THE JOBS
# ============================================
jobs
# Output:
# [1]-  Running                 sleep 300 &
# [2]+  Stopped                 top

# The + is the current job (top, because it was just suspended)
# The - is the previous job (sleep)

# ============================================
# PART 4: RESUME THE SUSPENDED JOB IN THE BACKGROUND
# ============================================
# Resume top in the background
# It will fail to read the terminal and suspend again
bg %2
# Output: [2]+ top &
# The top process tries to read the terminal
# The terminal driver sends SIGTTIN
# The process is suspended again
# Output: [2]+ Stopped top

# ============================================
# PART 5: BRING A JOB TO THE FOREGROUND
# ============================================
# Bring the sleep job to the foreground
fg %1

# The shell waits for the sleep to finish
# Press Ctrl+C to interrupt it
# Output: ^C

# ============================================
# PART 6: CHECK AND CLEAN UP
# ============================================
jobs
# Output:
# [2]+  Stopped                 top

# Kill the stopped job
kill %2
# The job is terminated

jobs
# Output: (empty)

The six parts cover starting a background job, suspending a foreground job, listing, resuming in the background, bringing to the foreground, and cleaning up. What the session demonstrates is that the & returns the prompt, Ctrl+Z stops the process, bg resumes it, fg brings it back, and jobs shows the state.


Quick Reference

Job Control Commands

CommandEffect
command &Start in background
Ctrl+ZSuspend foreground job
bg %nResume suspended job in background
fg %nResume job in foreground
jobsList jobs

Job States

StateMeaning
RunningExecuting in the background
StoppedSuspended, can be resumed
DoneCompleted

Job References

ReferenceMeaning
%nJob number n
%% or %+Current job
%-Previous job
%stringJob whose command starts with string
%?stringJob whose command contains string

jobs Flags

FlagEffect
-lShow PIDs
-rRunning jobs only
-sStopped jobs only
-nChanged status only

Best Practices

โœ… Do This:

# Start a long task in the background
./backup.sh &

# Suspend the foreground process
# Press Ctrl+Z

# Resume it in the background
bg

# List jobs with PIDs
jobs -l

# Bring the current job back
fg

โŒ Don’t Do This:

# Start a terminal-dependent app in the background
vim & # suspends immediately with SIGTTIN

# Forget the job number when multiple jobs exist
fg # resumes the current job, which may not be the one you want

# Assume the background job's output is suppressed
sleep 100 & # output still goes to the terminal

Common Pitfalls

PitfallWhy It HappensFix
vim & suspendsBackground job cannot read terminalRun in foreground
bg does nothingJob already running in backgroundCheck jobs
fg wrong jobNo job number, used current jobUse fg %n
Output interleavesBackground stdout not redirectedRedirect to file
Job lost after shell exitJobs are children of the shellUse nohup or disown

Real-World Examples

1. Start in background

./long-task.sh &

2. Suspend foreground

# Press Ctrl+Z

3. Resume in background

bg

4. Bring to foreground

fg

5. List jobs

jobs

6. List with PIDs

jobs -l

7. Kill a job

kill %1

8. Reference by name

fg %ce

9. Current job

fg %+

10. Previous job

fg %-

Visual

Job States

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  START                                       โ”‚
โ”‚  command &  โ†’ Running (background)           โ”‚
โ”‚  command    โ†’ Running (foreground)           โ”‚
โ”‚         โ”‚                                    โ”‚
โ”‚         โ–ผ                                    โ”‚
โ”‚  Ctrl+Z  โ†’ Stopped                           โ”‚
โ”‚         โ”‚                                    โ”‚
โ”‚    โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”                               โ”‚
โ”‚    โ”‚         โ”‚                               โ”‚
โ”‚    โ–ผ         โ–ผ                               โ”‚
โ”‚  bg %n    fg %n                              โ”‚
โ”‚    โ”‚         โ”‚                               โ”‚
โ”‚    โ–ผ         โ–ผ                               โ”‚
โ”‚  Running  Running                            โ”‚
โ”‚  (background) (foreground)                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Terminal Access

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  FOREGROUND                                  โ”‚
โ”‚  โ†’ receives Ctrl+C, Ctrl+Z                   โ”‚
โ”‚  โ†’ can read/write terminal                   โ”‚
โ”‚                                              โ”‚
โ”‚  BACKGROUND                                  โ”‚
โ”‚  โ†’ immune to keyboard signals                โ”‚
โ”‚  โ†’ read attempt โ†’ SIGTTIN โ†’ suspend          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Job Reference

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  jobs                                        โ”‚
โ”‚  [1]-  Running    sleep 100 &                โ”‚
โ”‚  [2]+  Stopped    top                        โ”‚
โ”‚                                              โ”‚
โ”‚  + = current job                             โ”‚
โ”‚  - = previous job                            โ”‚
โ”‚                                              โ”‚
โ”‚  fg %2   โ†’ bring top to foreground           โ”‚
โ”‚  kill %1 โ†’ terminate sleep                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Background startcommand &
SuspendCtrl+Z
Resume in backgroundbg %n
Resume in foregroundfg %n
List jobsjobs
List with PIDsjobs -l
Kill jobkill %n
Current job%+ or %%
Previous job%-

Key takeaways:

  • & starts a job in the background. The shell returns the prompt immediately and prints the job number and PID. The job continues running, and the shell tracks it .
  • Ctrl+Z suspends the foreground job. The process is stopped, not killed, and the shell returns the prompt. The job is in the “Stopped” state and can be resumed .
  • bg resumes a suspended job in the background. It is equivalent to having started the job with &. fg resumes it in the foreground and gives it terminal access .
  • A background job cannot read the terminal. If it tries, the terminal driver sends SIGTTIN and suspends it. This is why interactive programs must run in the foreground .
  • The job number is the shell’s identifier. %1 refers to job 1, %+ to the current job, and %- to the previous job. The jobs command shows the numbers and the +/- markers .
  • Jobs are children of the shell. When the shell exits, the jobs are terminated unless they are detached with nohup or disown. The nohup command makes the process immune to the hangup signal .

Remember: Job control is the shell’s mechanism for managing multiple tasks from a single terminal. The ampersand starts a job in the background, Ctrl+Z suspends the foreground job, bg and fg move it between the background and the foreground, and jobs lists what the shell is tracking. The terminal driver enforces the access rules: only the foreground job can read from the terminal, and a background job that tries is suspended. The job number is the short reference, and the + and - markers identify the current and previous jobs. The LFCS exam expects you to know these commands and the states, because they are the tools for managing the processes that a single shell session starts.


Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!