CPU temperature is one of the first vitals to check when a host slows down, a fan suddenly screams, or a workload that used to finish in five minutes now takes twenty. A CPU that crosses its thermal limit will throttle — silently drop its frequency to protect the silicon — and you will only see the symptom (slow performance, missed SLOs, dropped frames) rather than the cause unless you are already watching the sensor.
This guide covers how to read CPU temperature on Linux and Windows using built-in interfaces and free tools, how to interpret the numbers, what safe ranges look like, and how to wire the metric into continuous server monitoring.
Why CPU temperature matters
Modern x86 CPUs (Intel and AMD) and most ARM SoCs expose per-core digital thermal sensors (DTS). The OS reads them from on-die registers; vendors specify two thresholds you should care about:
- Tj,max — the maximum junction temperature the part is rated for. Crossing it triggers thermal throttling: the CPU clocks itself down and reduces voltage to bring temperature back under Tj,max.
- Critical / shutdown — a few degrees above Tj,max. The platform forces an emergency shutdown to avoid damage.
For most desktop and server parts:
- Idle: ~30–45 °C
- Normal load: ~50–75 °C
- Heavy / sustained load: ~75–90 °C (acceptable but worth watching)
- Throttling zone: typically 95–105 °C (Tj,max is part-specific — see below)
ARM SBCs (Raspberry Pi, etc.) usually start throttling around 80 °C.
Always check your part's datasheet instead of trusting a generic number. Quick lookups:
- Intel Ark: https://ark.intel.com/ — search the SKU, look for "TJUNCTION".
- AMD: product page → "Max Temps".
- Raspberry Pi: 80 °C soft, 85 °C hard.
Linux
Linux exposes thermal data through sysfs under /sys/class/hwmon/ and /sys/class/thermal/. Almost every userspace tool — lm-sensors, sensors, psensor, Prometheus exporters — is a wrapper over those files.
Quickest read: sysfs
No packages required:
# Read every thermal zone
for f in /sys/class/thermal/thermal_zone*/temp; do
zone=$(dirname "$f")
type=$(cat "$zone/type")
temp=$(cat "$f")
printf "%s: %d °C\n" "$type" $((temp / 1000))
done
thermal_zone*/temp reports milli-degrees Celsius, which is why the script divides by 1000. type tells you what the zone is (x86_pkg_temp, acpitz, cpu-thermal, etc.).
lm-sensors (the standard tool)
# Debian/Ubuntu
sudo apt install lm-sensors
# RHEL/CentOS/Rocky/Alma
sudo dnf install lm_sensors
# Arch
sudo pacman -S lm_sensors
Detect available sensors once per host:
sudo sensors-detect --auto
Read them:
sensors
Typical output on an Intel server:
coretemp-isa-0000
Adapter: ISA adapter
Package id 0: +52.0°C (high = +80.0°C, crit = +100.0°C)
Core 0: +49.0°C (high = +80.0°C, crit = +100.0°C)
Core 1: +51.0°C (high = +80.0°C, crit = +100.0°C)
Core 2: +50.0°C (high = +80.0°C, crit = +100.0°C)
Core 3: +52.0°C (high = +80.0°C, crit = +100.0°C)
Key fields:
- Package id 0 — overall socket temperature; this is the number to alert on.
- Core N — per-core readings; useful for spotting one runaway core (often a workload pinned to a single core, or asymmetric cooling).
- high / crit — vendor-reported thresholds; these come straight from MSR registers.
For continuous output every 2 seconds:
watch -n 2 sensors
Filter to just the package temperature for scripts/alerts:
sensors | awk '/^Package id 0:/ { print $4 }'
# → +52.0°C
AMD Ryzen / EPYC
On modern AMD parts you may need the k10temp (Ryzen) or zenpower (some workstation/server SKUs) module. lm-sensors will pick it up automatically; the relevant chip name in sensors output is k10temp-pci-…:
k10temp-pci-00c3
Adapter: PCI adapter
Tctl: +47.6°C
Tdie: +47.6°C
- Tdie — actual die temperature. Use this.
- Tctl — same value with a vendor-applied offset for fan control. Older Ryzen Threadripper used to add up to +27 °C here; ignore it for monitoring.
One-liner for monitoring scripts
Returns the highest core temperature in °C as an integer — easy to alert on:
sensors -u 2>/dev/null \
| awk -F'[: ]+' '/_input/ && /temp/ { if ($2+0 > max) max = $2+0 } END { print int(max) }'
ARM SBCs (Raspberry Pi, etc.)
Raspberry Pi OS ships a one-shot reader:
vcgencmd measure_temp
# temp=48.3'C
Or read sysfs directly (works on any ARM Linux):
cat /sys/class/thermal/thermal_zone0/temp
# 48312 → 48.3 °C
Check whether the Pi is currently throttling:
vcgencmd get_throttled
# throttled=0x0
Anything other than 0x0 means it has thermally-throttled at some point since boot — see https://www.raspberrypi.com/documentation/computers/os.html#vcgencmd for the bitfield.
IPMI / BMC (servers)
Bare-metal servers expose temperatures via the BMC. Use ipmitool from any host that can reach the BMC LAN:
ipmitool sensor list | grep -iE 'cpu|temp'
# CPU1 Temp | 41.000 | degrees C | ok
# CPU2 Temp | 39.000 | degrees C | ok
This works even if the OS is unresponsive — the BMC reads the sensors out-of-band.
Windows
Windows does not ship a built-in CPU temperature command. The values exist (the firmware exposes them via ACPI), but the OS surface for them is incomplete on most consumer hardware. You will rely on free third-party tools, or on PowerShell/WMI when ACPI thermal zones are populated.
PowerShell / WMI (when it works)
Get-WmiObject -Namespace "root\wmi" -Class MSAcpi_ThermalZoneTemperature |
Select-Object InstanceName,
@{ Name = "Celsius"; Expression = { ($_.CurrentTemperature - 2732) / 10 } }
The raw value is in tenths of a Kelvin, so (value − 2732) / 10 converts to °C.
This works on many laptops and OEM desktops. On most custom-built desktops and servers, the WMI class either returns nothing or only reports the chassis/ACPI thermal zone — not the actual CPU die. If Get-WmiObject returns no instances, fall back to the tools below.
Core Temp (lightweight, CPU-only)
- Site: https://www.alcpu.com/CoreTemp/
- Tiny, focused, free for personal use.
- Reads DTS via the same on-die sensors
lm-sensorsuses. - Shows per-core temperature, Tj,max, current load, and the offset from Tj,max ("Distance to TjMax") — the most useful single number.
- Built-in logging to CSV is handy for short captures.
HWiNFO64 (deepest detail, free)
- Site: https://www.hwinfo.com/
- Free for personal use; commercial license available.
- Reads everything: every core, package, motherboard, GPU, NVMe, fan, voltage rail.
- Sensors-only mode (
Sensorsbutton on launch) is the one you want for monitoring. - Right-click a sensor → Logging Start to capture to CSV.
- Can expose readings via shared memory for dashboard tools (Rainmeter, AIDA64, etc.).
Open Hardware Monitor / LibreHardwareMonitor (free, open source)
- https://openhardwaremonitor.org/ (older) and https://github.com/LibreHardwareMonitor/LibreHardwareMonitor (active fork).
- Open source, no installer required.
- Exposes sensor data over a built-in HTTP server (
/data.json) — easy to scrape from a script or pull into Prometheus via an exporter. - Good choice for unattended servers because you can read it remotely without RDP.
Other options
- Ryzen Master — official AMD utility. Useful on Ryzen / Threadripper for accurate Tdie + per-CCX readings.
- Intel XTU (Extreme Tuning Utility) — official Intel utility. Good for K-series desktops; overkill for servers.
- Speccy / CPUID HWMonitor — fine for one-off reads; less ideal for continuous monitoring.
Reading temperature from the command line
Most third-party tools also publish a CLI or shared-memory channel. With HWiNFO, enable Shared Memory Support in settings, then any client (a small PowerShell helper or a Prometheus exporter such as windows_exporter with the right collector) can read live values without running HWiNFO interactively.
For ad-hoc checks where WMI works:
function Get-CpuTempC {
Get-WmiObject -Namespace "root\wmi" -Class MSAcpi_ThermalZoneTemperature |
ForEach-Object { [math]::Round(($_.CurrentTemperature - 2732) / 10, 1) }
}
Get-CpuTempC
Continuous monitoring (production)
Reading temperature once is diagnosis. Catching a thermal problem before the fan fails or the room AC dies is monitoring — and that needs continuous collection plus alerting.
With Xitoring
Install Xitogent on the host (Linux or Windows). Once the agent is running, CPU temperature flows into Xitoring along with CPU load, memory, disk, and network — no extra plugins required. You can:
- Open the host in the Xitoring dashboard and view current and historical CPU temperature.
- Set a threshold trigger (e.g. "alert when CPU temperature ≥ 85 °C for 5 minutes") and route the alert to email, SMS, Slack, PagerDuty, or any other channel.
- Correlate temperature spikes against CPU load and process metrics on the same timeline — the fastest way to confirm whether the heat is being caused by a runaway process or by a cooling problem.
Install instructions: https://xitoring.com/docs/server-monitoring/install-xitogent/ — pick Linux or Windows.
With Prometheus + Grafana
Linux: node_exporter exposes hwmon temperatures out of the box at node_hwmon_temp_celsius. Example alert rule:
- alert: CpuTempHigh
expr: max by (instance) (node_hwmon_temp_celsius{chip=~"coretemp.*|k10temp.*"}) > 85
for: 5m
labels: { severity: warning }
annotations:
summary: "CPU temperature high on {{ $labels.instance }}"
Windows: windows_exporter with the thermalzone collector enabled exposes windows_thermalzone_temperature_celsius. Note this is the ACPI thermal zone, which (as on the WMI path) may not always reflect die temperature. For accurate per-core data on Windows, scrape LibreHardwareMonitor's /data.json instead.
Operational tips
- Alert on Tj,max minus a margin, not on a fixed number. "≥ 85 °C" triggers correctly on a 100 °C-rated desktop part but never trips on a 105 °C-rated server part being lightly stressed. A rule like
temp > tjmax - 10ages better. - Watch the package temperature, not the hottest core. Per-core readings are noisy: a single core under heavy single-threaded load can be 10 °C above the average, but the package is what governs throttling.
- Throttling has a unique fingerprint. On Linux, run
dmesg -T | grep -iE 'thermal|throttle'after a slowdown. On Intel, throttling events also show up in/proc/cpuinfo'scpu MHzdropping below the base clock under load. On Windows, HWiNFO surfaces a "Thermal Throttling" yes/no flag. - Sustained high temperature is usually airflow, not the CPU. Before reseating heatsinks: check the air filter, intake/exhaust direction, and ambient room temperature. A blocked filter can add 10–15 °C to package temperature.
- Datacenter racks are the inverse problem. Most enterprise servers throttle because the rear of the rack is recirculating hot air, not because the CPU is unusually loaded. Compare temps across hosts in the same rack — if every host is hot, the room/rack is the issue.
- Virtual machines may not see real temperatures. Inside a VM,
lm-sensorstypically returns nothing useful, and WMI returns the host's ACPI zone or no data at all. Monitor temperature on the hypervisor, not inside the guest.
Troubleshooting
sensorsprintsNo sensors found!. Runsudo sensors-detect --autoand reboot (orsudo modprobe coretemp k10tempto load common modules without rebooting). Inside a VM this is expected — there are no thermal sensors to expose.- AMD Ryzen reports
Tctl20+ °C aboveTdie. Older Threadripper / first-gen Ryzen added an offset toTctlfor fan-control headroom. UseTdiefor monitoring; if the kernel only exposesTctl, subtract the documented offset for that SKU. Get-WmiObject MSAcpi_ThermalZoneTemperaturereturns no instances on Windows. The motherboard does not populate ACPI thermal zones for the CPU. Use Core Temp, HWiNFO, or LibreHardwareMonitor instead.- Temperature looks pinned at exactly 50 °C or 100 °C. Some hypervisors and a few BIOS implementations return a constant placeholder. Confirm by stressing the CPU (
stress-ng --cpu 0 --timeout 60s) — if the value never moves, the sensor isn't real. - Per-core readings disagree by 20+ °C under load. Often a thermal-paste / mounting problem (one part of the IHS is making poor contact). Reseat the cooler and re-apply paste. If only one core is hot, also check for a workload pinned to that core (
taskset/ CPU affinity). - Server is throttling but ambient temperature is fine. Inspect the BMC sensor list (
ipmitool sensor list) for fan RPM — a single failed fan in a redundant array is a common, quiet cause. Most BMCs will alert, but only if the trap target is configured.
Summary
The minimum-viable mental model:
- Linux:
sensors(lm-sensors) for interactive checks,/sys/class/hwmon/or/sys/class/thermal/for scripts. On Ryzen, useTdie. - Windows: PowerShell/WMI when it works; otherwise Core Temp, HWiNFO, or LibreHardwareMonitor. The latter exposes JSON over HTTP — ideal for unattended servers.
- Servers: read out-of-band via the BMC (
ipmitool sensor list) so you still get readings when the OS is wedged. - Alert on Tj,max minus a margin (typically 10 °C) rather than a fixed number, because thresholds vary by SKU.
- Wire it into continuous monitoring — Xitoring with Xitogent, or Prometheus with
node_exporter/windows_exporter/ LibreHardwareMonitor — so a slow rise gets caught before it becomes a throttling incident.
Temperature is one of the cheapest signals to collect and one of the most diagnostic when something goes sideways. Once it is in your dashboard alongside CPU load and memory, the next "why is this host slow?" question usually answers itself.