Linux Performance

Fixing High CPU Usage on Linux Servers (Real-World Checklist)

By Nikhil Bhangale··2 min read

Diagnose load averages, pinpoint runaway processes, and implement long-term guards with systemd and cgroups.

Fixing High CPU Usage on Linux Servers (Real-World Checklist)

High CPU usage on a Linux server is one of those issues that sneaks up on you — everything looks fine until a monitoring alert fires or users start complaining about slow response times. This is the checklist I use every time I encounter elevated load averages in production.

Step 1: Check Load Averages

Start with the basics:

uptime
# 17:42:01 up 12 days,  3:14,  2 users,  load average: 4.21, 3.89, 3.45

A load average above the number of CPU cores means your system is consistently overloaded. Check core count:

nproc
# 4

In this case, a load of 4.21 on a 4-core machine means it's at capacity.

Step 2: Identify Top Processes

top -b -n 1 | head -30

Or for a cleaner snapshot:

ps aux --sort=-%cpu | head -20

Look for processes with consistent %CPU above 50%. Don't panic at single spikes — look for sustained usage.

Step 3: Check for Runaway Processes

A runaway process is often a script with an infinite loop, a zombie worker, or a PHP-FPM child that didn't die cleanly:

# Find processes in uninterruptible sleep (D state)
ps aux | awk '{if ($8 == "D") print $0}'

Processes stuck in D state are usually waiting on I/O — check disk health too.

Step 4: Check systemd Service Status

If the culprit is a system service:

systemctl status nginx php8.2-fpm mysql
journalctl -xe -u php8.2-fpm --since "1 hour ago"

Step 5: Apply cgroups CPU Limits

To prevent a single service from consuming all CPU:

# Create a cgroup slice for your web services
systemctl set-property php8.2-fpm.service CPUQuota=150%
systemctl set-property mysql.service CPUQuota=200%

This limits PHP-FPM to 1.5 cores and MySQL to 2 cores, leaving headroom for the OS.

Step 6: Long-Term Guard with systemd

Add CPU accounting to your service units:

[Service]
CPUAccounting=yes
CPUQuota=150%
MemoryAccounting=yes
MemoryMax=512M

Outcome

After applying these steps on a recent client server, we reduced average CPU from 85% to under 40% during peak traffic. The primary culprit was an uncapped PHP-FPM worker pool spawning too many children under load.

Always profile before limiting. The goal is guardrails, not starvation.

#linux#performance#systemd#cgroups#cpu
← Back to all posts