Process Management

Understanding processes separates people who can debug a stuck system from people who just reboot it. Everything running on a Unix box is a process — it has a PID, an owner, a parent, a working directory, and a set of open file descriptors. Once you can see that structure clearly, a lot of mysterious system behaviour starts making sense.

What's Running

$ ps aux             # all processes, BSD-style flags (most commonly used)
$ ps -ef             # all processes, POSIX-style
$ ps aux | grep nginx   # find processes matching a name
$ pgrep -l nginx        # cleaner: list PIDs and names matching "nginx"
$ pidof nginx           # just the PIDs

Process State Codes

The STAT column in ps aux output tells you what the process is doing:

CodeStateNotes
RRunning or runnableActively using or waiting for CPU
SSleepingWaiting for I/O, a signal, or a timer — normal
DUninterruptible sleepWaiting on I/O — cannot be killed; usually a disk or NFS problem
ZZombieFinished but parent hasn't collected its exit status
TStoppedPaused (SIGSTOP or Ctrl+Z)

Processes in state D (uninterruptible sleep) are typically stuck on a dying disk or an unresponsive network filesystem. kill -9 won't work on them — you often have to reboot.

Process Hierarchy

$ pstree -p              # full process tree with PIDs
$ ps -o pid,ppid,cmd     # show PID and parent PID for every process

Every process has a parent. PID 1 (systemd or init) is the ancestor of everything. When you run a command from a shell, the shell forks a child to run it. Understanding parent-child relationships helps when you're trying to figure out why a process keeps restarting — something is respawning it.

Signals

Signals are how you communicate with a running process. Most people only know kill -9, which is the sledgehammer — it works but the process has no chance to clean up:

SignalNumberMeaningCan be caught?
SIGTERM15Polite termination — process can handle it and clean upYes
SIGKILL9Force kill — cannot be caught or ignoredNo
SIGHUP1Hangup — daemons traditionally reload config on SIGHUPYes
SIGSTOP19/17Pause a process (like Ctrl+Z)No
SIGCONT18/19Resume a paused processYes
SIGINT2Interrupt (Ctrl+C in terminal)Yes
$ kill -SIGTERM 1234    # or: kill -15 1234
$ kill -SIGKILL 1234    # or: kill -9 1234
$ kill -SIGHUP 1234     # reload config (nginx, apache, etc.)

$ pkill nginx           # kill by name
$ pkill -HUP nginx      # send HUP to all processes named nginx
$ killall firefox       # kill all processes with this exact name

Best practice: try SIGTERM first, wait a few seconds, then SIGKILL if the process doesn't exit. Most well-written daemons handle SIGTERM gracefully.

Job Control

Job control lets you manage multiple things in a single shell session:

$ long_command &        # run immediately in background
$ long_command
^Z                      # Ctrl+Z suspends the foreground process
$ bg                    # continue suspended job in background
$ fg                    # bring the most recent background job to foreground
$ fg %2                 # bring job 2 to foreground specifically
$ jobs                  # list all jobs in current session
# Survive session logout:
$ nohup ./myscript.sh &         # immune to hangup; output goes to nohup.out
$ disown %1                     # detach job 1 from the shell (no nohup file)

# Better: use tmux or screen for long-running sessions
$ tmux new -s mysession         # start a named tmux session
$ tmux attach -t mysession      # reattach after disconnecting

Finding What's Using a Resource

# What's using a port?
$ lsof -i :8080
$ ss -tlnp | grep 8080

# What process has this file open?
$ lsof /var/log/app.log

# What's blocking an unmount?
$ fuser /mnt/usb               # shows PIDs using the mount
$ fuser -k /mnt/usb            # kill all processes using it

# What files does a process have open?
$ lsof -p 1234

Process Priority: nice and renice

Nice values range from -20 (highest priority, hogs CPU) to 19 (lowest, yields to everything). Regular users can only lower priority (raise the nice value). Root can raise priority:

$ nice -n 10 ./heavy_job.sh      # start with lower priority (nice 10)
$ renice +10 -p 1234             # lower priority of a running process
$ renice -5 -p 1234              # raise priority (needs root)
$ renice +15 $(pgrep ffmpeg)     # lower priority of all ffmpeg processes

Monitoring Over Time

CommandShowsNotes
topLive CPU/memory by processPress 1 to see per-CPU, M to sort by memory
htopSame but friendlierTree view, mouse support, colour coding
vmstat 1System-wide stats every secondGood for spotting memory pressure (swap activity)
iostat -x 1Per-device I/O stats every second%util column shows if a disk is saturated
sar -u 1 10CPU usage, 10 samplesPart of sysstat package

When a system is slow, the sequence: check top for CPU/memory hogs → check iostat to see if it's I/O-bound → check lsof if a specific process seems to be holding resources.

References