Chapter 08Lesson 03~50 minutes

Foreground, Background, Jobs, nohup, and tmux

Control shell jobs safely, understand terminal ownership and hangups, and choose between backgrounding, nohup, tmux, and real service supervision.

Job controltmuxHands-on lab

Learning objectives

By the end of this lesson

  • Distinguish a shell job from a process and a foreground process group.
  • Use &, jobs, fg, bg, and job specifications safely.
  • Explain why terminal disconnects can terminate or disrupt ad hoc workloads.
  • Use nohup and tmux appropriately while recognizing their limitations.
  • Choose a service manager or scheduler for durable production workloads.

1. Foreground means control of the terminal

Interactive shells organize pipelines into jobs and process groups. The terminal has one foreground process group at a time. That group receives terminal-generated signals such as interrupt from Ctrl+C, suspend from Ctrl+Z, and input from the keyboard. A background process group can continue running but normally cannot read from the controlling terminal.

Interactive shell job-control model
flowchart TB
  T["Terminal and TTY driver"] --> F["Foreground process group"]
  T -. input and Ctrl+C .-> F
  S["Interactive shell"] -->|launches pipelines| F
  S --> B1["Background job group 1"]
  S --> B2["Stopped job group 2"]
  F -->|Ctrl+Z / SIGTSTP| B2
  S -->|fg| F
  S -->|bg| B2

A job can contain several processes, such as a pipeline. Job identifiers like %1 are shell-local references, while PIDs identify individual processes system-wide within a PID namespace.

2. Launch and inspect shell jobs

# Start a background job and capture its last process PID.
sleep 300 &
pid=$!

# Show jobs known to this shell, including PIDs.
jobs -l

# Refer to jobs by shell job specification.
# fg %1       # Bring job 1 to the foreground.
# bg %1       # Continue a stopped job in the background.

# Send TERM to the controlled process and collect its status.
kill -TERM "$pid"
wait "$pid" 2>/dev/null || true

jobs only knows jobs created by the current shell and retained in its job table. A process can exist without being a current-shell job. Conversely, one job can represent a multi-process pipeline. Use jobs -l, ps, and process groups together when precision matters.

Do not automate with job numbers

Job IDs are interactive shell state and can change as jobs start or finish. Scripts should capture PIDs, use wait semantics, or delegate lifecycle to a supervisor.

3. Stopped is not terminated

Pressing Ctrl+Z usually sends SIGTSTP to the foreground process group. The process remains in memory but is not scheduled until continued. bg continues it in the background; fg continues it and restores foreground terminal control.

# Controlled demonstration without keyboard interaction.
sleep 300 &
pid=$!

kill -TSTP "$pid"
ps -o pid,ppid,pgid,tpgid,stat,comm,args -p "$pid"

kill -CONT "$pid"
ps -o pid,ppid,pgid,tpgid,stat,comm,args -p "$pid"

kill -TERM "$pid"
wait "$pid" 2>/dev/null || true

A stopped deployment, migration, or terminal utility may appear “hung” while actually waiting in state T. Check state and terminal/job context before escalating.

4. Disconnects, SIGHUP, and nohup

When a terminal closes, the session and shell may send SIGHUP to associated jobs. Programs may also fail later because standard input, output, or error still points to a closed terminal. nohup arranges for the launched command to ignore SIGHUP and commonly redirects terminal output.

lab="$HOME/devops-academy/linux/chapter08/lesson03"
mkdir -p "$lab"

nohup bash -c '
  for n in 1 2 3 4 5; do
    printf "%s step=%s\n" "$(date --iso-8601=seconds)" "$n"
    sleep 2
  done
' > "$lab/nohup-demo.log" 2>&1 &
pid=$!

printf 'nohup_pid=%s\n' "$pid"
wait "$pid"
cat "$lab/nohup-demo.log"

nohup is useful for a small ad hoc command, but it does not provide restart policy, structured logging, dependency ordering, health checks, resource limits, startup on boot, or ownership records. It is not a production service manager.

5. tmux preserves an interactive workspace

tmux is a terminal multiplexer. A tmux server owns sessions containing windows and panes. Your terminal attaches as a client and can detach without terminating the session. This is valuable for remote administration, long interactive investigations, and training labs.

TaskCommandPurpose
Createtmux new -s incidentStart a named session
Listtmux list-sessionsSee active sessions
DetachCtrl+b dDisconnect client, preserve session
Attachtmux attach -t incidentReturn to the session
Capturetmux capture-pane -pExport visible pane history
Removetmux kill-session -t incidentTerminate the named session

A tmux session protects against client disconnects, not host reboot or service failure. Apply access control carefully because anyone who can access the tmux server socket may control sessions and view terminal content.

6. Choose the right lifecycle owner

Shell background

Short interactive task

Use when you remain connected and can monitor or wait for completion.

nohup

Small ad hoc detached command

Use with explicit input/output paths and a cleanup plan.

tmux

Interactive remote session

Use when you need to detach and later resume a terminal workflow.

systemd / scheduler

Durable operational workload

Use for restart, boot integration, identity, logs, resources, dependencies, and auditability.

CI jobs should be owned by the CI runner, scheduled work by a scheduler or systemd timer, and long-running services by a service manager. Avoid hiding important production work inside personal shells.

7. Hands-on lab: observe jobs, groups, and detachment

Start a background pipeline, inspect its process group, stop and continue it, then run a detached tmux session when tmux is available.

lab="$HOME/devops-academy/linux/chapter08/lesson03"
mkdir -p "$lab"

# Start a pipeline as a shell job.
{ while :; do date --iso-8601=seconds; sleep 2; done; } \
  | sed -u 's/^/pipeline /' > "$lab/pipeline.log" &
pid=$!

jobs -l
ps -o pid,ppid,pgid,sid,tpgid,stat,comm,args --ppid "$$"

kill -TSTP "$pid"
sleep 1
ps -o pid,ppid,pgid,sid,tpgid,stat,comm,args -p "$pid"
kill -CONT "$pid"
sleep 3
kill -TERM "$pid"
wait "$pid" 2>/dev/null || true

tail "$lab/pipeline.log"

# Optional tmux demonstration.
if command -v tmux >/dev/null; then
  session="da-ch8-l3-$$"
  tmux new-session -d -s "$session" \
    "printf 'session started at %s\\n' '\$(date --iso-8601=seconds)'; sleep 5; printf 'done\\n'"
  tmux list-sessions
  sleep 6
  tmux capture-pane -p -t "$session" > "$lab/tmux-output.txt" || true
  tmux kill-session -t "$session" 2>/dev/null || true
  cat "$lab/tmux-output.txt"
fi

Verification checklist

8. Common mistakes

Assuming & survives logout

Backgrounding changes terminal foreground placement; it does not establish durable supervision.

Leaving output attached to a terminal

A detached command can block or fail when writing to a closed terminal. Redirect all streams intentionally.

Running production services in tmux

tmux is an interactive workspace, not a restart-capable service manager.

Confusing stopped with dead

A stopped job still owns memory, descriptors, locks, and other resources.

9. Knowledge check

Question 1. What receives terminal-generated Ctrl+C?

Question 2. What does nohup not provide?

Question 3. Why is tmux useful over SSH?

10. Summary

Shell job control is built around jobs, process groups, sessions, and the controlling terminal. Backgrounding, stopping, continuing, nohup, and tmux solve different interactive problems. Durable services and scheduled workloads need a real lifecycle owner such as systemd, a scheduler, or a CI runner—not a forgotten personal shell.

Next lesson

Signals, kill, pkill, and Graceful Shutdown

Next, you will control process lifecycle through signals and design shutdown behavior that preserves data and service reliability.

11. Further reading

  • Bash Reference Manual sections on job control and signals.
  • jobs(1p), nohup(1), setsid(1), and tmux(1).
  • termios(3) and credentials(7) for terminal, session, and process-group concepts.

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.