Process Monitoring & Control¶
Every running program is a process, and diagnosing "the box is slow" or "my job is stuck" almost always starts with looking at what's actually running, how much of the machine it's using, and whether it will respond to a request to stop. This page covers inspecting processes and controlling them — including the difference between asking a process to stop and forcing it to.
TL;DR — in 30 seconds:
ps auxis a snapshot of every process right now;topis the same information, live and continuously refreshing.killdoesn't "kill" by default — it sends a signal;SIGTERM(the default) asks a process to shut down cleanly,SIGKILL(-9) terminates it immediately with no cleanup.- A command ending in
&runs in the background;jobslists your shell's background jobs,fg/bgmove one to the foreground/background.
1. Inspecting processes¶
ps aux— a snapshot of every process on the system:a(all users' processes),u(user-oriented format: owner, CPU%, memory%),x(include processes with no controlling terminal). Key columns:PID(process ID, the number every other command below needs),%CPU,%MEM,STAT(process state),CMD(the command that launched it).top(orhtopwhere installed) — the same kind of information asps aux, but live: it refreshes continuously and sorts by resource usage by default, so it's the tool to reach for when you need to watch what's happening right now, not just a one-time snapshot.$?— after any command finishes, this shell variable holds its exit code:0means success, any non-zero value means failure (the specific non-zero value is program-defined and often documented as meaning something specific, e.g. "config error" vs "network error").
stateDiagram-v2
[*] --> Running
Running --> Sleeping: waiting on I/O
Sleeping --> Running: I/O ready
Running --> Stopped: SIGSTOP / Ctrl+Z
Stopped --> Running: SIGCONT / fg
Running --> Zombie: process exits,<br/>parent hasn't reaped it
Zombie --> [*]
Running --> [*]: SIGTERM/SIGKILL handled,<br/>process exits
2. Foreground, background, and jobs¶
Every command you run occupies your terminal (foreground) until it finishes — unless you tell the shell otherwise:
| Action | Command |
|---|---|
| Start a command in the background | append & (e.g. long_task.sh &) |
| Suspend the current foreground job | Ctrl+Z (sends SIGSTOP) |
| List this shell's background/suspended jobs | jobs |
| Bring a job back to the foreground | fg %<job-number> (or just fg for the most recent) |
| Resume a suspended job in the background | bg %<job-number> |
| Keep a background job running after you log out | nohup command & |
A background job started with plain & is still tied to your terminal session — if the session ends, the
job normally gets a SIGHUP too. nohup explicitly detaches it from that signal so it keeps running.
3. Signals and kill¶
kill is misleadingly named: it doesn't inherently terminate anything — it sends a signal to a
process, and what happens next depends on which signal and how (or whether) the process handles it.
| Signal | Number | Meaning |
|---|---|---|
SIGTERM |
15 | Default for kill — politely ask the process to terminate; a well-behaved program catches this and cleans up (closes files, flushes buffers) before exiting. |
SIGKILL |
9 | Immediate, unconditional termination — the process cannot catch, block, or clean up on this one; the kernel just ends it. |
SIGHUP |
1 | Originally "the terminal hung up"; many long-running services (daemons) treat it as "reload your config" instead. |
SIGINT |
2 | What Ctrl+C sends — interrupt the foreground process. |
SIGSTOP |
— | Suspend the process (like Ctrl+Z); cannot be caught or ignored. |
kill <PID>— sendsSIGTERM(the default; give it a chance to clean up first).kill -9 <PID>(orkill -SIGKILL <PID>) — sendsSIGKILL; use only onceSIGTERMhas failed to stop it, since it skips any cleanup the process would otherwise have done.kill -l— list every signal name and number.
Common gotchas
- Reaching for
kill -9first. Fix: try plainkill(SIGTERM) first and give the process a moment to exit cleanly —SIGKILLskips cleanup entirely (open files, temp state, in-flight writes), which is fine for a truly stuck process but unnecessarily destructive for one that would have exited fine on its own. - Confusing a process's exit code with its output. Fix:
$?only tells you success/failure as a number — it says nothing about what happened; read the process's actual stdout/stderr (or logs) to diagnose why it failed. - Assuming
&alone survives you logging out. Fix: a plain background job is still attached to your terminal session and typically receivesSIGHUPwhen it ends; usenohup(or a proper service manager) for anything that must outlive your session. - Not knowing the difference between "high CPU" and "stuck." Fix:
top'sSTATcolumn tells you the actual state —R(running, genuinely using CPU) versusD(uninterruptible sleep, usually waiting on disk/network I/O) look identical in "the process is using resources" terms but need completely different fixes.
Check yourself — why doesn't kill -9 let a process save its state or close open files before exiting?
SIGKILL is handled directly by the kernel, not delivered to the process for it to catch or respond
to — the process has no opportunity to run any cleanup code at all. It is immediate and unconditional,
which is exactly why it's a last resort, not a first move.
Check yourself — you start backup.sh &, then close your terminal. What likely happens to it, and how would you have prevented that?
It likely receives SIGHUP when the session ends and stops, because a plain background job is still
attached to the terminal session. Running it as nohup backup.sh & instead would have detached it from
that signal so it kept running after logout.
You can defend this when you can read a ps aux/top snapshot to find a specific process's PID and
resource usage, explain the difference between SIGTERM and SIGKILL and why you'd choose one over the
other, and move a job between foreground and background without losing it.