Course outline

Linux / Basic: command-line foundations / Lesson 5

Follow processes, jobs, and signals

Understand process lifetimes, inspect selected processes, and distinguish graceful termination from forced termination.

About 4 min readContent reviewed
On this page

Lesson goals

  • Connect parent processes, PIDs, and exit status.
  • Distinguish a shell job from an operating-system process.
  • Choose signals based on documented behavior.

Processes have identities and lifetimes

A process is a running program with credentials, open descriptors, memory mappings, and a current directory. A process ID identifies it only during a lifetime; the kernel may later reuse that number. A parent starts children and collects their completion status with wait. A program can replace its executable image through exec without changing its process ID. Threads share much of a process’s state while executing independently. These distinctions explain why a single command can create several processes and why a name alone is an unreliable target.

Inspect selected processes

ps presents a snapshot rather than continuous truth. Choose explicit columns such as PID, PPID, state, and command; inspect the owning user before acting. A sleeping state is usually normal waiting, not proof of a hung process. A zombie has exited but its parent has not yet collected the status, so repeatedly sending it a kill signal cannot help. /proc exposes current process information when permissions allow. Arguments and environments can contain secrets, so avoid publishing unfiltered process listings or collecting another user’s details unnecessarily.

bash Track one child created by the example
sleep 1 &
child=$!
ps -p "$child" -o pid=,ppid=,stat=,comm=
wait "$child"
printf 'completed=%s\n' "$?"

The PID values vary. The example inspects only its new sleep process and waits for it; normal completion prints completed=0.

Job control belongs to the interactive shell

An interactive Bash job usually corresponds to a pipeline and its process group. A trailing & starts work asynchronously, and $! records the most recent background process identifier. jobs lists the current shell’s jobs, not every process in the system. Ctrl-Z normally requests terminal suspension; bg resumes a stopped job in the background, and fg gives a job the terminal again. A stopped job is not complete. Noninteractive scripts should manage child PIDs and wait explicitly rather than assume interactive job numbering is available.

Signals request specific actions

kill sends a signal; its name does not mean every invocation immediately destroys a process. SIGTERM requests termination and permits a program to clean up if it has installed a handler. SIGINT usually comes from Ctrl-C to the foreground process group. SIGKILL terminates without allowing a handler, while SIGSTOP cannot be handled either. Prefer symbolic names because some signal numbers vary by architecture. Before signaling, confirm ownership, current identity, and the intended scope. Broad name matching can affect unrelated processes or a newly reused PID.

bash Handle a signal inside a disposable child shell
bash -c 'trap "echo term-observed; exit 0" TERM; kill -s TERM "$$"'
Expected output
term-observed

The inner Bash installs a handler and sends TERM to itself. No unrelated PID is targeted. The trap prints a message and exits successfully.

Background work needs a lifetime policy

Putting & after a command does not make it a reliable service. Terminal closure, session policies, inherited descriptors, and unhandled signals can still end it. nohup changes hangup handling but does not provide startup ordering, health checks, or restart supervision. For recurring or long-lived workloads, a service manager or scheduler is a better model. In a small script, record each child, wait for completion, and propagate failures. If you cancel work, allow bounded cleanup time and document what temporary data may remain.

Common errors and fixes

Signaling by a guessed PID

Why it happens
A stale listing or copied number identifies the wrong lifetime.
How to fix it
Recheck the selected process and its owner before acting.
Prevent it next time
Capture children directly with $! and keep their scope narrow.

Using SIGKILL first

Why it happens
Forced termination was mistaken for normal shutdown.
How to fix it
Prefer a documented graceful mechanism and bounded waiting.
Prevent it next time
Learn cleanup and shutdown requirements before cancellation.

Treating a stopped job as finished

Why it happens
Ctrl-Z suspended execution instead of terminating it.
How to fix it
Inspect jobs and deliberately resume or terminate the lab job.
Prevent it next time
Distinguish stopped, running, and exited states.

Check your understanding

1. Why can a zombie remain after SIGKILL?

Show worked solution

Its executable work already ended. Only the small record needed for the parent’s wait remains. The remedy is to diagnose why the parent is not reaping children; repeatedly signaling the exited child cannot make it perform cleanup or collect itself.

2. A script starts two children and exits immediately. Describe a more reliable completion contract.

Show worked solution

Capture both child PIDs immediately, wait for each, record each result, and return a documented failure if either required task fails. Decide how cancellation reaches both children and what cleanup is required. Background startup alone cannot certify completion.

Key takeaways

  • Inspect process identity and scope before sending a signal.
  • Use wait to turn child completion into a result.

Official references