>
← Back to Linux

Linux Process Management: ps, top, kill, and systemd Explained

Every Linux system runs dozens of processes simultaneously—some visible, most hidden. To keep your system stable and performant, you need to monitor what's running and terminate what's broken. The ps, top, and kill commands, combined with systemd, give you complete control over process behavior. Here's how to use them like a pro.

Understanding Linux Processes

A process is an instance of a running program with its own memory space, file descriptors, and system resources. Every process has a unique Process ID (PID), a parent process ID (PPID), and ownership (user/group). The kernel scheduler decides which process runs at any given moment, managing CPU time across all active processes.

Why does this matter? A runaway process can consume 100% CPU. A memory leak can exhaust RAM. A zombie process can block system resources. Process management is how you prevent chaos. Let's start with viewing what's running.

The ps Command: Static Process Snapshot

The ps command displays a static snapshot of running processes. It's lightweight, scriptable, and perfect for finding specific processes or generating reports.

Basic ps Usage

ps aux

This shows every process on the system with full details:

Filtering and Searching with ps

Finding a specific process is crucial when you need to manage it:

ps aux | grep nginx

This searches for all processes containing "nginx". Be careful—the grep command itself will appear in the results. A better approach uses the -f flag with pgrep:

pgrep -a nginx

This shows PIDs and full command lines for all nginx processes without the grep command appearing.

Viewing Process Hierarchy

Understanding parent-child relationships helps when troubleshooting. View the process tree:

ps aux --forest

Or use the dedicated tree viewer:

pstree -p

The -p flag adds PIDs, making it easier to identify specific processes in the hierarchy.

The top Command: Real-Time Monitoring

While ps gives you a snapshot, top provides real-time monitoring. It updates every second (by default) and shows which processes are consuming the most resources right now.

Starting top

top

You'll see a summary at the top:

Below that, you see individual processes sorted by CPU usage by default. High load averages (above your CPU count) mean the system is overloaded. Zombie processes that don't disappear indicate a parent process isn't reaping them properly.

Interactive top Commands

Once top is running, you can interact with it:

Running top in Batch Mode

For scripts and monitoring systems, use batch mode:

top -b -n 1 | head -20

The -b flag runs non-interactively, and -n 1 limits it to one iteration. Pipe to head to show just the summary, or capture the output for analysis.

The kill Command: Terminating Processes

Sometimes processes must be stopped. The kill command sends signals to processes. It's not actually killing—it's sending a message, and the process decides how to respond.

Understanding Signals

Linux defines about 30 signals. The most important ones:

Using kill

First, find the PID:

pgrep -a postgres

Then send a signal. By default, kill sends SIGTERM:

kill 2451

This is polite—the process gets a chance to exit cleanly. If it doesn't respond after a few seconds, escalate:

kill -9 2451

The -9 sends SIGKILL, which immediately terminates the process. Use this only when SIGTERM fails.

Killing Multiple Processes

To kill all processes matching a name, use pkill:

pkill -f "python script.py"

The -f flag matches against the full command line, not just the process name. This is more precise than grepping and parsing PIDs manually.

systemd: Modern Process Management

Modern Linux distributions use systemd as their init system. It manages the boot process, system services, and dependencies between services. Understanding systemd is essential for production work.

Units and Services

In systemd terminology, a "unit" is any resource it manages—usually a service. A service unit represents a long-running process. Unit files are stored in /etc/systemd/system/ or /usr/lib/systemd/system/.

Here's a simple unit file for a hypothetical web application:

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

[Service]
Type=simple
User=webapp
ExecStart=/opt/myapp/bin/server
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Key sections:

Essential systemctl Commands

Manage services with systemctl:

systemctl start nginx        # Start the service
systemctl stop nginx         # Stop the service
systemctl restart nginx      # Restart the service
systemctl reload nginx       # Reload config (no downtime)
systemctl enable nginx       # Auto-start on boot
systemctl disable nginx      # Don't auto-start
systemctl status nginx       # Show current status
systemctl is-active nginx    # Check if running (scriptable)

To see all services and their status:

systemctl list-units --type=service

Viewing Logs with journalctl

systemd logs go to the journal. View them with journalctl:

journalctl -u nginx              # Show nginx logs
journalctl -u nginx -f           # Follow logs (like tail -f)
journalctl -u nginx --since "1 hour ago"  # Last hour
journalctl -u nginx -n 50        # Last 50 lines

The journal is searchable and structured, making debugging much easier than traditional syslog.

Service Dependencies

systemd respects dependencies. If a service requires another service to be running first, systemd handles the startup order. Define dependencies in the unit file:

[Unit]
After=postgresql.service
Wants=redis.service

After means "don't start until this is running." Wants means "start this if possible, but don't fail if it's unavailable."

Practical Workflow: Finding and Fixing a Runaway Process

Let's use everything together. Your application is using 95% CPU:

Step 1: Identify the culprit

top

You see java at the top, consuming 95% CPU. Press shift+m to see memory too. Note the PID.

Step 2: Get details

ps -p 4521 -o pid,ppid,cmd,etime

This shows the full command, parent PID, and elapsed time. You recognize it as the application that crashed.

Step 3: Stop it gracefully

kill 4521

Wait 5 seconds.

Step 4: Force kill if needed

ps -p 4521 && kill -9 4521

The ps -p 4521 checks if it's still running. If yes, kill it forcefully.

Step 5: Restart via systemd

systemctl restart myapp

systemd restarts it according to its configuration, handling dependencies and logging.

Step 6: Check logs