When a Linux system is experiencing high CPU, I typically start with the top command.
By default, top is real time, meaning that the top output will refresh every few seconds. The -n 1 option can be used to display a snap shot of top.
top -n 1
Sometimes, simply issuing the top command will spot one or more processings using the majority of the CPU. In this example, a Java process is using 90% of the CPU.
PID User PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMANDS
4594 root 20 0 417768 144754 5803 S 90.0 5.2 0:41:49 Java
It's important to recognize the Linux system may have more than 1 CPU core. The nproc command can be used to list the number of CPU cores the Linux system is using.
~]# nproc
4
In this example, since the Linux system has 4 CPU cores, the max CPU for the system is 400%, thus if a process is using 100% CPU, that's only 25% of the total available CPU.
Here is my go-to script for capturing CPU once every 5 seconds.
#!/bin/bash
IFS=$'\n'
log_file="/tmp/cpu.log"
while true; do
# Get number of CPU cores
cpu_cores=$(nproc)
echo "[$(date '+%m/%d/%Y %H:%M:%S.%s')] Server has $cpu_cores CPU cores" | tee --append $log_file
# Get overall CPU usage (100% per core, so divide by cores to get real percentage)
cpu_idle=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/")
cpu_used=$(echo "100 - $cpu_idle" | bc)
echo "[$(date '+%m/%d/%Y %H:%M:%S.%s')] Overall CPU usage: ${cpu_used}% (${cpu_idle}% idle)" | tee --append $log_file
# Calculate threshold: if a process uses more than (100/cores)%, it's using more than 1 full core
threshold_per_core=$(echo "100 / $cpu_cores" | bc)
echo "[$(date '+%m/%d/%Y %H:%M:%S.%s')] Threshold per core: ${threshold_per_core}% (processes above this are using 1 or more full cores)" | tee --append $log_file
cpu=$(ps aux --sort=-%cpu | awk -v thresh="$threshold_per_core" 'NR==1 || $3 > thresh')
# Count the number of lines in the cpu variable
cpu_line_count=$(echo "$cpu" | wc -l)
if [ "$cpu_line_count" -eq 1 ]; then
echo "[$(date '+%m/%d/%Y %H:%M:%S.%s')] There are no processes currently using more than ${threshold_per_core}% CPU (threshold per core)" | tee --append $log_file
else
echo "[$(date '+%m/%d/%Y %H:%M:%S.%s')] Processes using more than 1 full CPU core (>${threshold_per_core}%):" | tee --append $log_file
for line in $cpu; do
echo "[$(date '+%m/%d/%Y %H:%M:%S.%s')] $line" | tee --append $log_file
done
fi
sleep 5
done
Running this script will return stdout and append lines to the log file like this.
[02/10/2026 13:18:41.1770751121] Server has 2 CPU cores
[02/10/2026 13:18:41.1770751121] Overall CPU usage: 6.2% (93.8% idle)
[02/10/2026 13:18:41.1770751121] Threshold per core: 50% (processes above this are using 1 or more full cores)
[02/10/2026 13:18:41.1770751121] There are no processes currently using more than 50% CPU (threshold per core)
One common cause of high CPU is a cron job that runs commands that cause high CPU. Check your cron table (crontab) to see if a scheduled job correlates to the time when there is high CPU. For example, perhaps a crontab job is creating gzip or bzip2 compressed archives of a certain directory, such as /etc, which may cause high CPU while the job is running.
Another cause of high CPU is an application that is doing something to use a lot of CPU. For example, if you have a web server (apache httpd ngnix) or an application server (tomcat websphere) installed on the system, the web app may be using excessive CPU.
Did you find this article helpful?
If so, consider buying me a coffee over at 