Skip to main content

Overview

The temperature functions retrieve readings from hardware temperature sensors including CPU, GPU, storage devices, and other components. This is essential for thermal monitoring and system health management.

Functions

func SensorsTemperatures() ([]TemperatureStat, error)
func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error)

Parameters

ctx
context.Context
Context for cancellation and timeout control

Returns

Returns a slice of TemperatureStat structures containing temperature data from all available sensors.

TemperatureStat Structure

The TemperatureStat struct represents a single temperature sensor reading.
type TemperatureStat struct {
    SensorKey   string  `json:"sensorKey"`
    Temperature float64 `json:"temperature"`
    High        float64 `json:"sensorHigh"`
    Critical    float64 `json:"sensorCritical"`
}

Fields

SensorKey
string
Unique identifier for the temperature sensor. Format varies by platform and sensor type.Examples:
  • "coretemp_core_0" - Intel CPU core 0
  • "coretemp_core_1" - Intel CPU core 1
  • "k10temp_tctl" - AMD Ryzen Tctl temperature
  • "nvme_composite" - NVMe SSD composite temperature
  • "acpitz" - ACPI thermal zone
  • "iwlwifi_1" - Intel wireless adapter
Temperature
float64
Current temperature reading in degrees Celsius.
High
float64
High temperature threshold in degrees Celsius. System may issue warnings or begin throttling when this temperature is reached. Returns 0 if threshold is not available or not supported by the sensor.
Critical
float64
Critical temperature threshold in degrees Celsius. System may shut down to prevent hardware damage when this temperature is exceeded. Returns 0 if threshold is not available or not supported by the sensor.

Platform Support

Linux

Linux provides the most comprehensive temperature monitoring through:Primary: hwmon interface
  • Location: /sys/class/hwmon/hwmon*/temp*_input
  • Alternative: /sys/class/hwmon/hwmon*/device/temp*_input (CentOS)
  • Provides current temperature, high threshold, and critical threshold
  • Sensor names from temp*_label files
  • Temperatures in millidegrees Celsius (divided by 1000)
Fallback: thermal_zone interface
  • Location: /sys/class/thermal/thermal_zone*/
  • Used on systems without hwmon (e.g., Raspberry Pi)
  • Reads from temp and type files
  • Limited threshold information

macOS (Darwin)

Temperature sensor access on macOS is limited:
  • Requires SMC (System Management Controller) access
  • May require additional permissions or tools
  • Sensor availability depends on hardware model
  • Often requires third-party libraries for full functionality

Windows

Temperature monitoring on Windows:
  • May use WMI (Windows Management Instrumentation)
  • Often requires vendor-specific drivers
  • Limited standardization across hardware
  • Some sensors may not be accessible

BSD (FreeBSD, OpenBSD)

BSD systems have varying levels of support:
  • Depends on kernel sensor framework
  • May require specific kernel modules
  • Sensor access varies by hardware

Sensor Types and Naming

CPU Sensors

coretemp
Intel CPUs
Intel Core processors report per-core temperatures:
  • coretemp_core_0, coretemp_core_1, etc.
  • coretemp_package_id_0 for overall package temperature
k10temp / zenpower
AMD CPUs
AMD Ryzen and EPYC processors:
  • k10temp_tctl - Control temperature
  • k10temp_tdie - Die temperature
  • k10temp_tccd1, k10temp_tccd2 - CCD temperatures

Storage Sensors

nvme
NVMe SSDs
NVMe drives report multiple temperatures:
  • nvme_composite - Overall drive temperature
  • nvme_sensor_1, nvme_sensor_2 - Individual sensors
drivetemp
SATA/SAS Drives
Traditional hard drives and SSDs:
  • drivetemp followed by device identifier

GPU Sensors

nouveau / amdgpu
Graphics Cards
GPU temperatures:
  • nouveau for NVIDIA with open-source driver
  • amdgpu for AMD graphics
  • radeon for older AMD cards

Other Sensors

acpitz
ACPI Thermal Zones
Generic motherboard thermal zones managed by ACPI.
iwlwifi
Intel Wireless
Intel wireless network adapter temperatures.
pch_
Platform Controller Hub
Chipset temperatures on Intel platforms.

Usage Examples

Basic Temperature Reading

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/v4/sensors"
)

func main() {
    temps, err := sensors.SensorsTemperatures()
    if err != nil {
        panic(err)
    }
    
    if len(temps) == 0 {
        fmt.Println("No temperature sensors found")
        return
    }
    
    fmt.Println("Temperature Readings:")
    fmt.Println("----------------------------------------")
    
    for _, temp := range temps {
        fmt.Printf("%-30s: %6.1f°C\n", temp.SensorKey, temp.Temperature)
    }
}

Display with Thresholds

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/v4/sensors"
)

func main() {
    temps, err := sensors.SensorsTemperatures()
    if err != nil {
        panic(err)
    }
    
    fmt.Println("Sensor                         | Temp  | High  | Critical | Status")
    fmt.Println("-------------------------------|-------|-------|----------|--------")
    
    for _, temp := range temps {
        status := "OK"
        if temp.Critical > 0 && temp.Temperature >= temp.Critical {
            status = "CRITICAL"
        } else if temp.High > 0 && temp.Temperature >= temp.High {
            status = "WARNING"
        }
        
        highStr := "-"
        if temp.High > 0 {
            highStr = fmt.Sprintf("%.1f", temp.High)
        }
        
        critStr := "-"
        if temp.Critical > 0 {
            critStr = fmt.Sprintf("%.1f", temp.Critical)
        }
        
        fmt.Printf("%-30s | %5.1f | %5s | %8s | %s\n",
            temp.SensorKey, temp.Temperature, highStr, critStr, status)
    }
}

CPU Temperature Monitoring

package main

import (
    "fmt"
    "strings"
    "github.com/shirou/gopsutil/v4/sensors"
)

func getCPUTemperatures() ([]sensors.TemperatureStat, error) {
    temps, err := sensors.SensorsTemperatures()
    if err != nil {
        return nil, err
    }
    
    cpuTemps := make([]sensors.TemperatureStat, 0)
    for _, temp := range temps {
        key := strings.ToLower(temp.SensorKey)
        if strings.Contains(key, "core") ||
           strings.Contains(key, "cpu") ||
           strings.Contains(key, "k10temp") ||
           strings.Contains(key, "coretemp") {
            cpuTemps = append(cpuTemps, temp)
        }
    }
    
    return cpuTemps, nil
}

func main() {
    cpuTemps, err := getCPUTemperatures()
    if err != nil {
        panic(err)
    }
    
    if len(cpuTemps) == 0 {
        fmt.Println("No CPU temperature sensors found")
        return
    }
    
    fmt.Println("CPU Temperatures:")
    
    var sum float64
    var max float64
    var min float64 = 999.0
    
    for _, temp := range cpuTemps {
        fmt.Printf("  %-25s: %.1f°C\n", temp.SensorKey, temp.Temperature)
        sum += temp.Temperature
        if temp.Temperature > max {
            max = temp.Temperature
        }
        if temp.Temperature < min {
            min = temp.Temperature
        }
    }
    
    avg := sum / float64(len(cpuTemps))
    fmt.Printf("\nAverage: %.1f°C | Min: %.1f°C | Max: %.1f°C\n", avg, min, max)
}

Temperature Alert System

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/v4/sensors"
)

type TempAlert struct {
    Sensor   string
    Temp     float64
    Level    string
    Threshold float64
}

func checkTemperatures() []TempAlert {
    temps, err := sensors.SensorsTemperatures()
    if err != nil {
        return nil
    }
    
    alerts := make([]TempAlert, 0)
    
    for _, temp := range temps {
        if temp.Critical > 0 && temp.Temperature >= temp.Critical {
            alerts = append(alerts, TempAlert{
                Sensor:    temp.SensorKey,
                Temp:      temp.Temperature,
                Level:     "CRITICAL",
                Threshold: temp.Critical,
            })
        } else if temp.High > 0 && temp.Temperature >= temp.High {
            alerts = append(alerts, TempAlert{
                Sensor:    temp.SensorKey,
                Temp:      temp.Temperature,
                Level:     "WARNING",
                Threshold: temp.High,
            })
        }
    }
    
    return alerts
}

func main() {
    alerts := checkTemperatures()
    
    if len(alerts) == 0 {
        fmt.Println("✓ All temperatures within normal range")
        return
    }
    
    fmt.Printf("⚠️  Temperature Alerts (%d):\n\n", len(alerts))
    
    for _, alert := range alerts {
        fmt.Printf("[%s] %s\n", alert.Level, alert.Sensor)
        fmt.Printf("  Current: %.1f°C | Threshold: %.1f°C\n\n",
            alert.Temp, alert.Threshold)
    }
}

Continuous Temperature Monitoring

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
    "github.com/shirou/gopsutil/v4/sensors"
)

func main() {
    fmt.Println("Temperature Monitor (Ctrl+C to exit)\n")
    
    // Setup signal handling for graceful shutdown
    sigChan := make(chan os.Signal, 1)
    signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
    
    ticker := time.NewTicker(3 * time.Second)
    defer ticker.Stop()
    
    for {
        select {
        case <-ticker.C:
            temps, err := sensors.SensorsTemperatures()
            if err != nil {
                fmt.Printf("Error: %v\n", err)
                continue
            }
            
            // Clear screen (simple version)
            fmt.Print("\033[H\033[2J")
            
            fmt.Printf("Temperature Monitor - %s\n",
                time.Now().Format("15:04:05"))
            fmt.Println("===========================================")
            fmt.Println()
            
            for _, temp := range temps {
                indicator := "  "
                if temp.Critical > 0 && temp.Temperature >= temp.Critical {
                    indicator = "🔴"
                } else if temp.High > 0 && temp.Temperature >= temp.High {
                    indicator = "🟡"
                } else {
                    indicator = "🟢"
                }
                
                fmt.Printf("%s %-30s: %5.1f°C",
                    indicator, temp.SensorKey, temp.Temperature)
                
                if temp.High > 0 {
                    fmt.Printf(" (H: %.0f°C)", temp.High)
                }
                if temp.Critical > 0 {
                    fmt.Printf(" (C: %.0f°C)", temp.Critical)
                }
                fmt.Println()
            }
            
        case <-sigChan:
            fmt.Println("\n\nShutting down...")
            return
        }
    }
}

Export to JSON

package main

import (
    "encoding/json"
    "fmt"
    "github.com/shirou/gopsutil/v4/sensors"
)

func main() {
    temps, err := sensors.SensorsTemperatures()
    if err != nil {
        panic(err)
    }
    
    jsonData, err := json.MarshalIndent(temps, "", "  ")
    if err != nil {
        panic(err)
    }
    
    fmt.Println(string(jsonData))
}

Filter by Temperature Range

package main

import (
    "fmt"
    "github.com/shirou/gopsutil/v4/sensors"
)

func main() {
    temps, err := sensors.SensorsTemperatures()
    if err != nil {
        panic(err)
    }
    
    const threshold = 60.0
    
    fmt.Printf("Sensors above %.0f°C:\n", threshold)
    fmt.Println("------------------------------")
    
    hotSensors := make([]sensors.TemperatureStat, 0)
    for _, temp := range temps {
        if temp.Temperature > threshold {
            hotSensors = append(hotSensors, temp)
        }
    }
    
    if len(hotSensors) == 0 {
        fmt.Println("None")
        return
    }
    
    for _, temp := range hotSensors {
        fmt.Printf("%-30s: %.1f°C\n", temp.SensorKey, temp.Temperature)
    }
}

Using Context with Timeout

package main

import (
    "context"
    "fmt"
    "time"
    "github.com/shirou/gopsutil/v4/sensors"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()
    
    temps, err := sensors.TemperaturesWithContext(ctx)
    if err != nil {
        if ctx.Err() == context.DeadlineExceeded {
            fmt.Println("Temperature reading timed out")
        } else {
            fmt.Printf("Error: %v\n", err)
        }
        return
    }
    
    fmt.Printf("Found %d temperature sensors\n", len(temps))
}

Performance Considerations

  • Reading temperatures is relatively lightweight
  • Safe to poll every few seconds
  • File I/O is cached by the kernel
  • Minimal CPU overhead

Error Handling

temps, err := sensors.SensorsTemperatures()
if err != nil {
    fmt.Printf("Error reading temperatures: %v\n", err)
    return
}

if len(temps) == 0 {
    fmt.Println("No temperature sensors found")
    fmt.Println("This may be normal on:")
    fmt.Println("  - Virtual machines")
    fmt.Println("  - Systems without sensor drivers")
    fmt.Println("  - Non-Linux platforms")
    return
}

Troubleshooting

  • Check if running in a virtual machine (sensors often not available)
  • Ensure proper kernel modules are loaded (lm-sensors on Linux)
  • Verify system has physical temperature sensors
  • Check permissions (some systems may require elevated privileges)
  • Not all sensors provide threshold information
  • High and Critical fields will be 0 when unavailable
  • This is normal behavior and should be handled in your code
  • Some sensors may require calibration
  • Verify sensor drivers are up to date
  • Compare with other monitoring tools
  • Some readings may be in different units (check documentation)

Common Use Cases

  • Server thermal monitoring and alerting
  • Overclocking safety monitoring
  • Datacenter environmental tracking
  • Hardware diagnostics and troubleshooting
  • Performance tuning (identifying thermal throttling)
  • Cooling system effectiveness validation
  • Long-term hardware health tracking

See Also

Build docs developers (and LLMs) love