Chapter 10Lesson 01~85 minutes

Processes, Subshells, Background Jobs, and PIDs

Bash is not only a command language; it is a process orchestrator. Understanding which operations stay in the current shell and which create child processes is fundamental to reliable DevOps automation.

BeginnerProcesses & concurrencyHands-on lab

Learning objectives

By the end of this lesson

  • Explain parent/child process relationships.
  • Distinguish builtins from external commands.
  • Use subshells for isolated state.
  • Start and identify background jobs.
  • Understand pipeline process boundaries.

1. Bash orchestrates processes

An external command normally runs as a child process of the shell. The child inherits environment, open descriptors, current directory, and credentials, but receives its own process identity.

Parent and child process model
flowchart TD
  B["Bash process"] --> C1["curl child"]
  B --> C2["grep child"]
  B --> C3["sleep child"]
printf 'shell PID=%s\n' "$$"
ps -o pid=,ppid=,stat=,command= -p "$$"

2. Builtins run inside the shell

Commands such as cd, read, printf, local, and export can execute inside Bash itself.

cd /tmp
printf 'PWD=%s\n' "$PWD"
Why this matters

An external child cannot permanently change its parent shell's working directory or shell variables.

3. Parentheses create an isolated subshell environment

name="parent"
(
  name="child"
  cd /tmp || exit 1
  printf 'inside name=%s pwd=%s\n' "$name" "$PWD"
)
printf 'outside name=%s pwd=%s\n' "$name" "$PWD"

Variable and directory changes made inside the parentheses do not normally propagate back to the parent shell.

4. Command substitution captures output from another process context

value=$(printf 'generated-value\n')
printf 'value=%s\n' "$value"

Command substitution captures stdout and removes trailing newlines. Treat it as a data-return boundary, not shared mutable shell state.

5. Ampersand starts asynchronous work

sleep 3 &
pid=$!

printf 'started pid=%s\n' "$pid"
printf 'parent continues immediately\n'

The parent shell does not wait automatically. The most recent asynchronous PID is available in $!.

6. $$, BASHPID, and $! answer different questions

ParameterMeaningUse
$$PID associated with the main shell contextCommon diagnostic identifier
BASHPIDPID of the current Bash processUseful inside Bash-created subshells
$!PID of most recently started asynchronous commandUse for wait/kill coordination
printf 'parent $$=%s BASHPID=%s\n' "$$" "$BASHPID"
(
  printf 'subshell $$=%s BASHPID=%s\n' "$$" "$BASHPID"
)

7. Interactive job control is not a production API

Interactive shells may use jobs, fg, and bg. Non-interactive automation should coordinate children with stored PIDs and wait.

sleep 2 &
pid=$!
wait "$pid"

8. Pipeline stages may run in separate process environments

count=0
printf '%s\n' a b c |
while IFS= read -r line; do
  ((count += 1))
done
printf 'count=%d\n' "$count"

Assignments made in a pipeline loop can disappear afterward because the loop may run in a subshell.

9. Process substitution can preserve loop state

count=0
while IFS= read -r line; do
  ((count += 1))
done < <(printf '%s\n' a b c)

printf 'count=%d\n' "$count"

10. Starting a process creates a lifecycle responsibility

A parent script should decide whether a child must finish, be canceled after parent failure, or intentionally outlive the script.

Lifecycle contract

Do not leave background-process lifetime to accident.

11. Hands-on lab: inspect process relationships

mkdir -p "$HOME/devops-academy/bash/chapter10/lesson01"
cd "$HOME/devops-academy/bash/chapter10/lesson01"

printf 'main $$=%s BASHPID=%s\n' "$$" "$BASHPID"

(
  printf 'subshell $$=%s BASHPID=%s\n' "$$" "$BASHPID"
  sleep 1 &
  child=$!
  printf 'subshell child=%s\n' "$child"
  wait "$child"
)

sleep 1 &
background=$!
printf 'main child=%s\n' "$background"
wait "$background"

Verification checklist

12. Knowledge check

Question 1. What does & do?

Question 2. What does $! contain?

Question 3. Why are parentheses useful?

Question 4. Should scripts depend on interactive job control?

13. Summary

Bash is a process orchestrator. External commands become child processes, subshells isolate state, background jobs continue asynchronously, and PIDs are the handles that let the parent coordinate lifecycle.

14. Further reading

  • GNU Bash Reference Manual — Pipelines, Lists, Job Control.
  • GNU Bash Reference Manual — Special Parameters and BASHPID.
  • POSIX shell execution model.
  • Linux ps(1) and proc(5).
Next lesson

wait, Job Coordination, and Exit Status

Continue Chapter 10 by making process lifecycle and concurrency behavior more explicit.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.