How to Check CPU Usage in Linux: The Complete Guide

Robert Johnson

I still remember the 3 AM page that changed how I think about CPU monitoring. Our production API was crawling, users were complaining, and I was frantically running commands I’d memorized without actually understanding what they told me. I knew top showed me numbers, but I didn’t know which numbers mattered or what to do about them.

That night taught me something critical: checking CPU usage isn’t about running a single command. It’s about understanding the story your system is trying to tell you. Let me show you how to read that story properly.

Why CPU Usage Matters (And What Most Guides Get Wrong)

Here’s the thing most tutorials skip: CPU usage and system load are not the same thing. I’ve seen servers with 90% CPU utilization running perfectly fine, and servers with 30% CPU that were grinding to a halt. The difference? Understanding what you’re actually measuring.

RackNerd Mobile Leaderboard Banner

CPU usage tells you what percentage of time your processor is actively executing instructions. Load average tells you how many processes are waiting in line for CPU time, disk I/O, or other system resources. As Brendan Gregg explains in his excellent analysis, Linux load averages include processes in uninterruptible sleep states, not just CPU-bound tasks.

This matters because when you’re troubleshooting, you need to know which metric is actually causing your problem. High CPU with low load average? You’ve got a compute-intensive process. Low CPU with high load average? You’re probably waiting on disk I/O or network operations.

The Quick Check: Using top to See CPU Usage

The top command is your first stop. It’s installed on virtually every Linux distribution, and it gives you a real-time view of your system.

top

When you run top, you’ll see something like this in the header:

%Cpu(s):  12.5 us,  3.2 sy,  0.0 ni, 83.1 id,  0.8 wa,  0.0 hi,  0.4 si,  0.0 st

Let me decode this, because it confused the hell out of me when I was starting out:

  • us (user): Time spent running user processes. This is your applications doing work.
  • sy (system): Time spent in the kernel. High system CPU usually means lots of system calls or I/O operations.
  • ni (nice): Time spent running low-priority processes. You’ll rarely see this unless you’ve manually adjusted process priorities.
  • id (idle): Time the CPU spends doing nothing. High idle is good – it means you have capacity.
  • wa (I/O wait): Time waiting for I/O operations to complete. If this is high, your bottleneck is disk or network, not CPU.
  • hi/si (hardware/software interrupts): Usually low unless you’re dealing with network-heavy workloads.
  • st (steal time): Only relevant in virtualized environments. High steal time means your hypervisor is giving your CPU cycles to other VMs.

The processes list below shows individual programs sorted by CPU usage. Press P to sort by CPU percentage (usually the default), or M to sort by memory usage instead.

Pro Tip: Press 1 in top to see individual CPU cores. On a multi-core system, a single-threaded process can show 100% CPU usage but only consume 25% of a quad-core system. I’ve debugged so many “high CPU” alerts that turned out to be perfectly normal single-threaded processes.

The Better Alternative: htop for Human Beings

I’ll be honest: I stopped using top for daily work years ago. htop is just better in almost every way. It’s colorful, interactive, and actually makes sense at a glance.

sudo apt install htop  # Debian/Ubuntu
sudo dnf install htop  # Fedora/RHEL
htop

htop shows you a visual bar graph for each CPU core at the top of the screen. Green bars represent user processes, red is kernel/system processes, and blue is low-priority processes. You can scroll through the process list with arrow keys, and F6 lets you sort by different columns.

What I love most about htop is that it’s intuitive. When I’m showing junior admins how to kill a runaway process, I can just say “press F9, select SIGTERM, hit enter.” No memorizing PIDs or cryptic keyboard shortcuts.

According to Jeff Geerling’s 2025 monitoring tools overview, newer alternatives like btop offer even more visual polish, but htop remains the reliable workhorse for most sysadmins.

When You Need More Detail: mpstat for Per-Core Analysis

Sometimes you need to go deeper than top or htop can show you. That’s when I reach for mpstat, which is part of the sysstat package.

sudo apt install sysstat  # Debian/Ubuntu
sudo dnf install sysstat  # Fedora/RHEL
mpstat -P ALL 1

This command shows CPU statistics for all processors, updated every second. The -P ALL flag displays each core individually, which is crucial for identifying CPU affinity issues or single-threaded bottlenecks.

I once debugged a database server that appeared to have low overall CPU usage but was actually bottlenecked on a single core handling all the write transactions. mpstat made that obvious immediately – one core was pegged at 100% while the other seven were mostly idle.

Troubleshooting High CPU Usage: A Practical Workflow

When you get an alert about high CPU usage, here’s my standard troubleshooting process:

Step 1: Identify the Culprit Process

Run top or htop and press P to sort by CPU usage. The process at the top of the list is your prime suspect. Note its PID (process ID) and command name.

Step 2: Investigate What That Process Is Doing

Use ps to get more details about the process:

ps aux | grep [PID]

This shows you the full command line, which often reveals configuration issues or unexpected arguments. I’ve found runaway cron jobs, misconfigured backup scripts, and forgotten test processes this way.

Step 3: Check If It’s I/O Wait, Not CPU

Look at the wa value in top. If I/O wait is high (above 20-30%), your problem isn’t actually CPU – it’s disk or network bottlenecks. In that case, you need to investigate with iostat or look at your network utilization instead.

This is where understanding the difference between CPU usage and load average becomes critical. A process can appear to be consuming CPU time when it’s actually just waiting for data.

Step 4: Determine If It’s Normal or a Problem

Not all high CPU usage is bad. If you’re running a video encoder, a compiler, or a scientific calculation, 100% CPU usage is exactly what you want – you’re getting your money’s worth from that hardware.

The question is: should this process be using this much CPU? A web server process using 90% CPU continuously is probably a problem. The same usage from ffmpeg is perfectly normal.

Step 5: Take Action

Depending on what you found, your options include:

  • Killing the process: If it’s a runaway script or hung process, terminate it cleanly with kill -15 [PID] or forcefully with kill -9 [PID].
  • Adjusting nice values: Use renice to lower the priority of non-critical processes so they don’t starve more important ones.
  • Optimizing the workload: Sometimes the answer is fixing inefficient code, adding database indexes, or caching results.
  • Adding more resources: If everything is working as designed and you’re still CPU-bound, it might be time to scale up or scale out.

Setting Up Automated CPU Monitoring

You can’t stare at top all day. That’s why I set up cron jobs to log CPU statistics automatically:

*/5 * * * * /usr/bin/mpstat 1 1 >> /var/log/cpu_usage.log

This records CPU stats every five minutes. When you get an alert about high CPU usage, you can go back and see what happened leading up to the incident.

For more sophisticated monitoring, tools like Prometheus, Grafana, or even simple scripts using sar (the system activity reporter) can track trends over time and alert you before problems become critical.

Understanding Load Average: The Other Half of the Story

When you run top or look at uptime, you see three numbers called load average:

load average: 1.23, 0.89, 0.56

These represent the average number of processes in a runnable or uninterruptible state over the last 1, 5, and 15 minutes. DigitalOcean’s load average guide provides an excellent deep dive into the math behind these numbers.

The rule of thumb: on a single-core system, a load average of 1.0 means the CPU is fully utilized. On a quad-core system, a load average of 4.0 means full utilization. Load average above your core count means processes are waiting for resources.

But here’s the catch: unlike other Unix systems, Linux includes processes waiting for I/O in the load average calculation. So you need to cross-reference load average with actual CPU usage and I/O wait to understand what’s really happening.

Common CPU Usage Scenarios I’ve Encountered

High user CPU, low system CPU: Application-level work. Usually normal unless it’s unexpectedly high.

High system CPU, low user CPU: Lots of kernel-level operations. Check for excessive context switching or system calls. I’ve seen this with misconfigured applications making thousands of tiny read/write calls instead of buffering properly.

High I/O wait, low CPU usage: You’re disk-bound. Time to check disk usage and I/O performance with iostat.

High load average, low CPU usage: Processes are waiting for something – usually disk I/O, network operations, or locks. This is where ps aux and looking at process states (the STAT column) helps identify what’s stuck.

The Tools You Actually Need

After a decade of doing this work, here’s what I actually use:

  • htop: My daily driver for interactive monitoring and quick process management.
  • mpstat: When I need per-core analysis or detailed CPU statistics.
  • top: On minimal systems or when I need something that’s guaranteed to be there.
  • sar: For historical analysis and identifying patterns over days or weeks.
  • Custom scripts: To log and alert on specific conditions that matter to my environment.

You don’t need fancy monitoring solutions for every situation. Sometimes a well-placed cron job and a shell script are exactly the right tool.

Final Thoughts: CPU Monitoring Is About Context

The biggest lesson I’ve learned about checking CPU usage is that the numbers mean nothing without context. 80% CPU usage might be a crisis or it might be perfectly normal, depending on what you’re running and what you expected.

The goal isn’t to keep CPU usage low – it’s to understand whether your system is doing what it’s supposed to do. I’d rather see a server working hard and getting things done than idling away with capacity I’m paying for but not using.

That said, understanding how to check CPU usage, interpret what you see, and troubleshoot problems when they arise is fundamental sysadmin knowledge. Master these tools, and you’ll save yourself a lot of 3 AM panic.

And hey, unlike me that first night, you’ll actually know which numbers to look at.