100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Bash

Background Jobs and Process Management

Learn how to launch, monitor, and control background jobs in bash using &, jobs, fg, bg, wait, and disown for scripts that need concurrency.

Process & Job ControlIntermediate9 min readJul 10, 2026
Analogies

Launching and Tracking Background Jobs

Appending & to a command launches it in the background, immediately returning control to the shell while the job runs asynchronously; bash tracks each backgrounded process in a job table accessible via the jobs builtin, which lists jobs with an index like [1] and their state (Running, Stopped, Done). The special variable $! holds the PID of the most recently backgrounded process, which is essential for later checking on it, waiting for it, or sending it a signal with kill.

🏏

Cricket analogy: Sending a specialist fielder to warm up in the outfield while the main game continues is like backgrounding a job with &: the main shell (batting side) keeps going while that process runs independently, tracked on the team sheet like bash tracks it in the jobs table.

bash
#!/usr/bin/env bash

# Launch three downloads in parallel
curl -sO https://example.com/file1.tar.gz &
pid1=$!
curl -sO https://example.com/file2.tar.gz &
pid2=$!
curl -sO https://example.com/file3.tar.gz &
pid3=$!

jobs -l              # show job table with PIDs

# Wait for all three, capturing individual exit codes
fail=0
for pid in "$pid1" "$pid2" "$pid3"; do
  if ! wait "$pid"; then
    echo "Job with PID $pid failed" >&2
    fail=1
  fi
done
exit "$fail"

Job Control: fg, bg, and Signals

In an interactive shell, Ctrl-Z suspends the foreground job by sending SIGTSTP, moving it into a Stopped state visible in jobs; bg %1 resumes job 1 in the background while fg %1 brings it back to the foreground, and %+/%- refer to the most recent and second-most-recent jobs respectively. Sending signals to a specific job uses kill %1 or kill -TERM $pid, and wait without arguments blocks until every background job the shell knows about finishes, while wait -n (bash 4.3+) returns as soon as any single one completes.

🏏

Cricket analogy: Ctrl-Z is like a captain calling for an unofficial drinks break mid-over, temporarily pausing play (Stopped state), while bg is like resuming play at a relaxed net-practice pace off to the side, and fg is bringing that same match back to the main center-wicket action.

Use disown to remove a job from the shell's job table without killing it, useful when you want a background process to survive the shell exiting (SIGHUP won't be sent to it). Combine with nohup command & or setsid command & for processes that must truly outlive the terminal session.

wait and Collecting Exit Statuses

wait $pid returns the exit status of that specific process, which is the standard way to know whether a parallel background task actually succeeded rather than merely finished; calling wait with no arguments waits for all currently tracked background jobs and always returns 0, so per-job status must be captured individually if failure detection matters. In bash 4.3+, wait -n blocks until the next background job completes and returns its exit status, which combined with a loop lets you build a simple worker pool that reacts to jobs finishing in any order rather than a fixed sequence.

🏏

Cricket analogy: Checking each specialist bowler's individual figures at the end of an innings (wait $pid) tells you exactly who took wickets and who was expensive, unlike just checking that the innings ended (bare wait), which tells you nothing about individual performance.

wait with no arguments always returns 0 even if every backgrounded job failed — it only reports whether the wait itself succeeded, not the jobs' outcomes. Always capture PIDs with $! and wait them individually (or use wait -n in a loop) if you need to detect partial failures in a parallel batch.

  • command & backgrounds a process immediately, returning control to the shell and setting $! to its PID.
  • jobs -l lists tracked background jobs with their PIDs and states (Running, Stopped, Done).
  • Ctrl-Z sends SIGTSTP to suspend the foreground job; bg resumes it in the background, fg brings it back.
  • wait $pid returns that job's actual exit status; bare wait always returns 0 regardless of job outcomes.
  • wait -n (bash 4.3+) waits for the next job to finish, enabling simple as-completed worker pool patterns.
  • disown removes a job from the job table so it survives shell exit without receiving SIGHUP.
  • Use nohup or setsid for background processes that must outlive the terminal session entirely.

Practice what you learned

Was this page helpful?

Topics covered

#Bash#AdvancedBashScriptingStudyNotes#DevOps#BackgroundJobsAndProcessManagement#Background#Jobs#Process#Management#StudyNotes#SkillVeris