Processes & Monitoring — ps, top, kill & Friends

See what's actually running, find what's eating your CPU or RAM, and stop it cleanly.

What a Process Is

Every running program is a process with a unique PID (process ID), an owner, and a parent that started it. Everything descends from PID 1 (systemd). When a server "feels slow," the answer is almost always hiding in the process list — the skill is knowing how to read it.

ps aux                       → every process, one snapshot
ps aux | grep nginx          → find a specific one
ps aux --sort=-%mem | head   → top 10 memory hogs
ps -ef --forest              → tree view: who started what
pgrep -a node                → PIDs + command line by name

Reading ps aux columns: %CPU and %MEM are self-explanatory; VSZ/RSS are virtual vs actual memory; STAT shows state — S sleeping (normal), R running, Z zombie, D stuck waiting on disk/network (a column full of D usually means storage trouble).

Live Views: top and htop

top is on every box; htop (one apt install away) adds color, scrolling, and mouse support. Inside top: M sorts by memory, P by CPU, k kills, q quits.

# The line that matters most in top:
load average: 0.42, 0.51, 0.60
#              1min  5min  15min

# Rule of thumb: load ≈ number of CPU cores = fully busy.
# 4.0 on a 4-core box is saturated; on a 16-core box it's idle chatter.
nproc                        → how many cores do I have?

High load with low CPU% means processes are waiting on disk or network, not compute — check iostat or that D-state column before blaming the CPU.

Memory: Reading free Correctly

free -h
#               total   used   free   buff/cache   available
# Mem:           7.8G   2.1G   0.4G         5.3G         5.4G

# "free" being tiny is FINE — Linux uses idle RAM as disk cache
# and gives it back instantly. The number that matters: "available".

If available approaches zero, the kernel's OOM killer starts executing your largest processes — check journalctl -k | grep -i oom when a service mysteriously vanished overnight.

Stopping Processes: Signals

kill doesn't kill — it sends a signal. The polite one asks the process to shut down cleanly; the last resort yanks it with no chance to save state. Always escalate in order:

kill 1234            → SIGTERM: "please exit cleanly" (default)
kill -9 1234         → SIGKILL: immediate, no cleanup — last resort
kill -HUP 1234       → many daemons reload config on this

pkill -f "python.*stuck_script"   → kill by command-line match
# For anything managed by systemd, prefer:
systemctl stop myapp              → lets systemd track the state

Why not always -9? SIGKILL skips cleanup — half-written files, orphaned lock files, un-flushed databases. If a process ignores SIGTERM for 30 seconds, then escalate.

The 5-Minute "Why Is It Slow?" Routine

# 1. Overall pressure — load vs core count
uptime && nproc

# 2. Who's eating CPU / RAM?
ps aux --sort=-%cpu | head -6
ps aux --sort=-%mem | head -6

# 3. Memory actually available?
free -h

# 4. Disk full? (a 100% root filesystem breaks everything weirdly)
df -h

# 5. Anything crash-looping or waiting on I/O?
systemctl list-units --failed
journalctl -p err --since "1 hour ago" --no-pager | tail -20

This routine answers 90% of "the server is acting weird" incidents before you ever need real monitoring — and when you outgrow it, that's your cue for the Prometheus + Grafana guide in the Guides section.

≈·*•—[ A|S ]—•*·≈

- Crafted by Axiom|Spectre