Linux Process Management: ps, top, and kill Aren't Enough

You’ve definitely run ps aux | grep something and called it a day. But Linux process management is way more powerful than the basics. Let’s dig into what’s really happening.

What Even Is a Process?

A process is just a running program. When you execute a binary, the kernel:

  1. Allocates memory
  2. Assigns a PID (Process ID)
  3. Sets up file descriptors (stdin, stdout, stderr)
  4. Starts executing instructions

Every process has a parent (except PID 1, which is init/systemd). Check the process tree:

pstree -p

Process States

Processes aren’t just “running” or “stopped”. They go through multiple states:

  • R (Running): Currently executing or ready to run
  • S (Sleeping): Waiting for an event (I/O, user input, etc.)
  • D (Uninterruptible Sleep): Waiting for disk I/O (can’t be killed!)
  • Z (Zombie): Finished executing but parent hasn’t read exit status
  • T (Stopped): Paused by a signal (Ctrl+Z)

See state of all processes:

ps aux
# S column shows state

Signals: How Processes Communicate

When you run kill, you’re sending a signal. SIGKILL (-9) isn’t the only option:

# Politely ask process to terminate
kill -TERM <PID>  # or kill -15 <PID>

# Force immediate termination (no cleanup!)
kill -KILL <PID>  # or kill -9 <PID>

# Pause process
kill -STOP <PID>  # Ctrl+Z does this

# Resume process
kill -CONT <PID>  # fg does this

# Reload config without restart
kill -HUP <PID>   # Many daemons support this

Use kill -l to see all available signals.

The Problem with kill -9

Everyone defaults to kill -9 but it’s dangerous. The process gets no chance to:

  • Close files properly
  • Flush buffers
  • Clean up child processes
  • Remove lock files

Always try kill -TERM first. Give it 5 seconds. Only then resort to -9.

Finding Resource Hogs

top is fine but htop is better. Install it:

sudo apt install htop  # Ubuntu/Debian
sudo yum install htop  # RHEL/CentOS

Better yet, use ps with custom formatting:

# Top 10 CPU consumers
ps aux --sort=-%cpu | head -11

# Top 10 memory consumers
ps aux --sort=-%mem | head -11

# Specific process CPU/memory
ps -p <PID> -o %cpu,%mem,cmd

Background Jobs and Disown

Start a long-running process in the background:

./long_running_script.sh &

But if you log out, it dies. Use nohup:

nohup ./long_running_script.sh &
# Output goes to nohup.out

Or disown to detach an already running job:

./long_running_script.sh &
disown

Even better, use screen or tmux for persistent sessions.

systemd: Modern Process Management

For production services, systemd is the way. Create a unit file:

[Unit]
Description=My Web App
After=network.target

[Service]
Type=simple
User=webuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/server
Restart=always

[Install]
WantedBy=multi-user.target

Save to /etc/systemd/system/myapp.service and:

sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl enable myapp  # Start on boot
sudo systemctl status myapp  # Check status

systemd handles restart on failure, logging, and dependencies automatically.

Debugging Stuck Processes

Process stuck in D state (uninterruptible sleep)? It’s waiting on I/O. Check what it’s doing:

# See what files it has open
lsof -p <PID>

# See system calls it's making
strace -p <PID>

# Check I/O wait
iostat -x 1

Zombie Processes

Zombies happen when a child process finishes but the parent hasn’t called wait(). They’re harmless (use zero resources) but if you have thousands, something’s wrong with the parent.

Find zombie parents:

ps aux | awk '$8=="Z" {print $2}' | xargs -I {} ps -o ppid= -p {}

Then fix or restart the parent process.

Understanding process management makes debugging production issues way easier. Most problems come down to signals, states, or resource contention - and now you know how to diagnose all three.