3 Ways to Check CPU and GPU Temperatures on Linux

3 Ways to Check CPU and GPU Temperatures on Linux

CPU temperature on Linux has two correct answers and each one fails on the wrong machine. Install lm-sensors and run sensors, or read a file under /sys/class/thermal.

A temperature appears only after a kernel driver recognises a sensor chip and publishes its registers as files. The first command is therefore a detection command, and the read commands follow from what it finds.

Where a Linux temperature number comes from

Nothing in user space measures heat. A driver binds to a sensor chip, and the kernel exposes that chip as a hardware monitoring device under /sys/class/hwmon, one directory per chip.

Each device carries a name file that identifies the driver and one or more temperature inputs.

Those inputs are measured in millidegrees Celsius, which is why a reading of 45000 means 45 degrees. The last three digits are the fraction you drop.

Diagram of five stages from a hardware sensor to a temperature reading on Linux
A reading exists only after a driver binds the chip and the kernel publishes its registers.

The chain from chip to screen is three steps. libsensors reads the kernel files, sensors prints what libsensors read, and sensors-detect loads the module when the driver is not built in.

Some hardware never registers a chip and uses a thermal zone instead, under /sys/class/thermal.

A zone carries a type file that names what it measures and a temp file in millidegrees. ARM boards lean on that interface heavily, which is why a Pi answers to firmware calls as well.

Before you install anything, find out what this machine exposes

I kept the detection step ahead of the read commands because the two fail for different reasons. That step costs two commands and can save an install.

Drivers create these files only when they recognise the hardware below them. An empty listing therefore means no driver bound a sensor at all, and no package can change that.

ls /sys/class/hwmon/
ls /sys/class/thermal/

A chip appears as hwmon0, hwmon1 and so on.

Knowing which driver to expect takes one more command. lscpu prints the vendor and the model, and those two fields decide the driver name.

lscpu | grep -E "Model name|Vendor ID"

The name file inside each directory says which driver claimed the chip, so coretemp means an Intel package sensor and k10temp means an AMD one. amdgpu covers a Radeon card.

cat /sys/class/hwmon/hwmon*/name

If both listings come back empty, the kernel has no sensor to report. Virtual machines, cloud instances and many containers sit in that state, because the hypervisor offers no chip for a driver to bind.

Root is needed for the detection step and for loading modules, never for reading a value. The read commands work as an ordinary user, which is what makes them usable on a locked-down server.

Read the CPU temperature with lm-sensors

lm-sensors turns a directory of files into one readable line per sensor, and it is the tool I reach for first on a machine I can install on. I installed it from the Ubuntu 24.04 archive at version 1:3.6.0-9build1.

Install and detect the chip

Install the package, then run the detection script once so the matching module is loaded at boot.

sudo apt install lm-sensors
sudo sensors-detect

The script probes CPUs, Super I/O chips, ISA ports and the SMBus in that order. It then offers to write the modules it found into the distribution’s module list, which is what makes a reading survive a reboot.

Automatic mode takes the default answer to every question. The man page states plainly that this is not necessarily safe, because probing an unknown chip can upset an SMBus.

sudo sensors-detect --auto

Read the value and its limits

A reading arrives with the chip’s own thresholds attached in parentheses.

Those numbers come from the chip, so they beat any table of safe temperatures by processor family. I would rather read them off the hardware than remember a table.

A reading block is three parts. The first line names the chip and the bus it sits on, the second names the adapter, and each sensor then gets its own line with the limits the chip reports.

Terminal output of sensors --help listing the lm-sensors options
The help output lists the flags that choose adapters, units and output format.

Run sensors –help and the flags that matter sit near the top of the output. -A drops the adapter line, -f switches to Fahrenheit, -j emits JSON for a script, and -u prints raw input names.

Tdie is the junction temperature, and Tctl carries a control offset that some models add. On AMD Ryzen the chip reports both, so compare Tdie against the crit value.

Watch the reading while the machine works

A single reading says little about a machine that throttles while you watch it.

watch re-runs the command on an interval and repaints the terminal in place. A load spike then shows up as a change in the value, and a system monitor such as glances puts the load and the temperature side by side.

watch -n 2 sensors -A

For anything scripted, take the JSON form and read the temp inputs by name. I would rather parse a stable key than a text block whose width changes with the chip count.

sensors -j | python3 -m json.tool | head -20

A window instead of a terminal

psensor draws the same libsensors values as graphs and can pin one reading into the desktop panel. conky covers the same ground when you want load and memory beside it.

It reads through lm-sensors, so on a machine with no chip it has nothing to plot either. Install it after the detection step rather than before.

sudo apt install psensor

Read the same value straight from the kernel

Everything sensors prints is already a file, so the reading stays available with nothing installed.

On a server where package installs are not allowed, that is the whole method. The kernel interface is also what you reach for when the package exists but no driver claimed the chip.

grep . /sys/class/hwmon/hwmon*/temp*_input

The same directory tree also carries the CPU frequency, which pairs with the temperature when a machine feels slow under load.

Each line prints the file that answered and the value it holds. Divide by a thousand for degrees Celsius, so 42000 becomes 42.

The thermal zone interface returns the same kind of number from a different directory.

Pairing the type file with the temp file tells you which zone is the processor package. A wireless card has a zone too, so the type file is what keeps you from reading the wrong one.

<pre class="wp-block-syntaxhighlighter-code">paste <(cat /sys/class/thermal/thermal_zone*/type) <(cat /sys/class/thermal/thermal_zone*/temp)</pre>

Try the zone path first on an ARM board, and on a laptop whose firmware publishes an ACPI zone but no monitoring chip. The zone labelled x86_pkg_temp is the Intel processor package, while SEN and pch entries belong to platform sensors.

Check the GPU temperature

GPU temperature lives in the vendor driver rather than the generic sensor layer, and the table below maps hardware to tool. When the card inside the case is a guess, CPU-X reports the model the driver sees.

CardToolCommandReading it gives
NVIDIA discretenvidia-sminvidia-smi -q -d TEMPERATURECurrent, slowdown and shutdown temperatures
NVIDIA scriptednvidia-sminvidia-smi –query-gpu=temperature.gpu –format=csvOne value per card, clean to log
AMD Radeonrocm-smirocm-smi -tShowtemp reports the current temperature
AMD through the kernelhwmoncat /sys/class/hwmon/hwmon*/nameLook for a chip named amdgpu
Raspberry Pivcgencmdvcgencmd measure_tempThe SoC sensor shared by CPU and GPU

The NVIDIA command deserves one warning from the vendor’s own documentation. Cards built in a module form factor that rely on case airflow usually provide no temperature reading at all, so an empty value there is expected behaviour.

nvidia-smi -q -d TEMPERATURE

The vendor documentation carries the flags for both tools. I used it for the NVIDIA and AMD commands instead of a memory of them, and on a Radeon card the kernel route needs the AMD driver in place before rocm-smi returns anything.

A directory under /sys/class/hwmon whose name file says amdgpu or nouveau holds an edge sensor in temp1_input. That number matches what the vendor tool reports, which is a useful cross-check.

Integrated graphics share the processor package sensor on the platforms I have looked at. There is no separate GPU reading to find, and the CPU value already covers it.

On a Raspberry Pi the firmware call returns the SoC sensor that the CPU and the GPU share. A single reading therefore describes both, and /sys/class/thermal/thermal_zone0/temp carries the identical value.

Check disk and NVMe temperature

Drives carry their own sensor, and the drive’s own log page is the one to read.

On an NVMe device that log is the SMART and health page. nvme-cli reads it, and the composite temperature sits near the top of the output.

sudo nvme smart-log /dev/nvme0

The command name changed upstream. nvme-cli 3.0 renamed it to nvme log smart and kept smart-log as a deprecated alias that prints a warning, so an older package needs the spelling above and a current one accepts either.

smartctl prints the temperature for SATA drives out of the attribute table. The drivetemp kernel module exposes the same value as a hwmon chip.

sudo smartctl -A /dev/sda

I checked the package list, and hddtemp is gone from Ubuntu 24.04. The install line that older material recommends fails before it can read anything.

apt-cache policy reporting no installation candidate for hddtemp
Ubuntu 24.04 offers no candidate for hddtemp, so the package cannot be installed.

The two log readers above replace it, and I would use them over a desktop widget because they work over SSH.

When every command says there is no sensor

lm-sensors prints the same sentence on a desktop that is missing a module and on a cloud instance that has no sensor at all. The two cases need opposite responses, so the message alone does not tell you which one you are in.

sensors
Terminal output reporting that sensors found no sensor chips
With no driver bound, sensors reports that it found nothing and points at sensors-detect.

Work down this list before installing a second tool.

  • No driver bound. Check /sys/class/hwmon again, because an empty directory means the kernel found no chip it could claim.
  • The module is not loaded. sensors-detect names the module it wants, and modprobe loads it for the current boot before you add it to the module list.
  • A virtual machine or cloud instance. The hypervisor presents no chip, so the guest kernel has nothing to bind and the provider’s console or a host-side agent is the only source left.
  • A container. The process shares the host kernel, so /sys shows the host’s chips, and a host without sensors hands that emptiness down.
  • A new processor. The chip may need a kernel newer than the one installed, which is the one case where a distribution upgrade changes the answer.

The kernel also logs a line when a package crosses its threshold, and that line names the core that throttled. journalctl -k keeps the history, which is how you confirm a thermal event hours after it happened.

journalctl -k | grep -i throttl

A sensor the kernel cannot see cannot be produced in user space. I would stop there rather than work through the package list, because the missing piece sits below the kernel.

What a safe reading looks like, and the command to keep watching

The threshold worth trusting is the one the chip reports about itself, and sensors prints it in parentheses next to every reading. The same number lives in the temp files under /sys/class/hwmon.

SignalWhat it meansWhat to do
highThe point where many chips begin to reduce clock speedRead it as a warning line, not a target
critThe shutdown boundary the chip enforces itselfInvestigate long before a reading approaches it
Tctl on RyzenJunction temperature plus a control offsetCompare Tdie with crit instead
80 °C or moreNamed in SUSE’s tuning guide as a sign of a cooling problemCheck airflow, dust and thermal paste before blaming software

Intel publishes a junction maximum near 100 °C for desktop parts and AMD sits a few degrees lower. Those figures move with each generation, so the number in the crit file is the one that applies to the chip in front of you.

A reading you can watch under load tells you more than a snapshot taken at idle.

When the reading climbs further than you want, the lever is the CPU frequency governor, which is what auto-cpufreq automates.

watch -n 2 sensors -A

Frequently asked questions

Why does sensors say it found no sensors?

The kernel bound no driver to a sensor chip, so there is no file for libsensors to read. That is normal inside a virtual machine, a cloud instance or a container. Check /sys/class/hwmon and /sys/class/thermal before installing anything else.

What is the difference between Tctl and Tdie on AMD Ryzen?

Tdie is the junction temperature. Tctl is the value the fan controller acts on, and some models add an offset to Tdie to produce it, so compare Tdie against the crit value.

How do I check GPU temperature without a desktop environment?

Use the vendor tool over SSH, with nvidia-smi -q -d TEMPERATURE for NVIDIA and rocm-smi -t for AMD. If the driver registers a hwmon chip, the temp1_input file under /sys/class/hwmon reports the same number.

Can I read the temperature on a Raspberry Pi the same way?

vcgencmd measure_temp returns the SoC sensor, and /sys/class/thermal/thermal_zone0/temp holds the same value in millidegrees. The CPU and the GPU share that one sensor.

Why did hddtemp stop working after I updated Ubuntu?

Ubuntu dropped the package, so there is no installation candidate on 24.04. Use nvme smart-log for NVMe drives and smartctl -A for SATA drives instead.

Is a temperature of 80 degrees a problem?

It depends on the crit value the chip reports next to the reading. SUSE’s tuning guide treats 80 °C or more as a sign of a cooling problem worth checking, and a load test that reaches that figure should be re-run once the airflow is fixed.