Create a CPU Frequency and Temperature Monitoring Bash Script for Linux-based Systems

This post will show you a way to monitor CPU frequency and temperature on Linux-based systems without aid of any programs or packages that are not commonly preinstalled on major GNU/Linux distributions. No extra hardware drivers are required: the magic is done merely by a short Bash script in just a few lines that only relies on mechanisms provided by the Linux kernel itself and some most essential Unix commands.

You can click here to jump to the script directly. If you are interested in seeing how I came up with the script, please read on.

If you are a Windows power user, you have probably used the Task Manager as a simple system monitor. It allows you to check CPU utilization and frequency, which are the most essential indicators of your system’s load. It is not the most comprehensive hardware monitoring tool, but it is the most handy and accessible utility. It exists in every Windows installation and can be fired up easily and quickly.

CPU statistics in Windows Task Manager

I have been struggling to find an ideal Windows Task Manager equivalent for GNU/Linux. As a GNOME user, the bundled System Monitor, as shown below, can only give me utilization of each CPU execution unit and does not show CPU frequency. htop is a great choice for hardware monitoring on GNU/Linux, but on some distributions, e.g. Fedora, it is not shipped by default and thus requires manually installing an extra package.

GNOME System Monitor does not show CPU frequency

Recently, I have discovered a simple command for getting each CPU execution unit’s frequency on an x86_64 system. It only relies on grep, a fundamental Unix program that should be preinstalled on every GNU/Linux system:

$ grep 'cpu MHz' /proc/cpuinfo

Sometimes I am also interested in seeing how CPU temperature is affected by system loads, especially when I am testing a cooling solution. In this case, I would want to see CPU temperature and CPU frequency at the same time. After a brief research, I found a way to get CPU temperature without help of any fancy packages like lm-sensors:

$ cat /sys/class/thermal/thermal_zone0/temp

The value shown in this command’s output is the CPU temperature in degrees Celsius multiplied by 1000. Stripping the three zeros off from the value gives the temperature value in degrees Celsius that we are familiar with. The following command performs this calculation directly in Bash:

$ echo $(($(cat /sys/class/thermal/thermal_zone0/temp) / 1000))

By the way, the commands I am mentioning here assume /sys/class/thermal/thermal_zone0 is for the CPU, not other hardware components like disk or wireless NIC. This is true for all of my devices that run a Linux-based system and allow me to check this, although there might be very rare situations where this assumption does not hold.

Now that we know the commands for getting CPU frequency and temperature, we can assemble them into a very simple Bash shell script for printing out CPU status:

#!/usr/bin/env bash

grep --color=never 'cpu MHz' /proc/cpuinfo
cpu_temp=$(($(cat /sys/class/thermal/thermal_zone0/temp) / 1000))
echo "cpu temperature : ${cpu_temp}"

You can put this script under a location in the PATH environment variable to run it easily from everywhere, e.g. ~/.local/bin on most GNU/Linux distributions. To check which locations are in PATH, you may use printenv PATH. In addition, do not forget to make the script executable (chmod +x).

And if you wish to continuously monitor CPU frequency and temperature, you can invoke the script with the watch program. It runs the command you specify every 2 seconds and prints the command output on the screen. In case you want to use another interval, you can use the -n option to specify it. For example, watch -n 1 runs the command you specify every 1 second.

Compatibility

This script should be compatible with all modern x86_64 CPUs from AMD and Intel. I have tested it on a Ryzen 7 4700U and a Core i5-7200U, and it has worked perfectly.

I have also tried it out on some aarch64 devices! The script could not read CPU frequency, but it was still able to get CPU temperature. The devices I tested were a Raspberry Pi 4 running Fedora 33’s Linux 5.10.9 kernel and a Nexus 9 Android tablet running Gentoo Android on an aging 3.10 kernel from a custom Android ROM.