mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-24 13:48:56 +08:00
[sensors][linux]: add ExLinux on sensors.
This commit references and fixes #1589. Thank you!
This commit is contained in:
parent
5cd488ff30
commit
5dfaba1490
79
sensors/ex_linux.go
Normal file
79
sensors/ex_linux.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
//go:build linux
|
||||||
|
|
||||||
|
package sensors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExTemperature represents Linux dependent temperature sensor data
|
||||||
|
type ExTemperature struct {
|
||||||
|
SensorKey string `json:"key"`
|
||||||
|
Min float64 `json:"min"` // Temperature min value.
|
||||||
|
Lowest float64 `json:"lowest"` // Historical minimum temperature
|
||||||
|
Highest float64 `json:"highest"` // Historical maximum temperature
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExLinux struct{}
|
||||||
|
|
||||||
|
func NewExLinux() *ExLinux {
|
||||||
|
return &ExLinux{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ex *ExLinux) TemperatureWithContext(ctx context.Context) ([]ExTemperature, error) {
|
||||||
|
var warns Warnings
|
||||||
|
|
||||||
|
files, err := getTemperatureFiles(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get temperature files, %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
temperatures := make([]ExTemperature, 0, len(files))
|
||||||
|
for _, file := range files {
|
||||||
|
var raw []byte
|
||||||
|
|
||||||
|
// Get the base directory location
|
||||||
|
directory := filepath.Dir(file)
|
||||||
|
|
||||||
|
// Get the base filename prefix like temp1
|
||||||
|
basename := strings.Split(filepath.Base(file), "_")[0]
|
||||||
|
|
||||||
|
// Get the base path like <dir>/temp1
|
||||||
|
basepath := filepath.Join(directory, basename)
|
||||||
|
|
||||||
|
// Get the label of the temperature you are reading
|
||||||
|
label := ""
|
||||||
|
|
||||||
|
if raw, _ = os.ReadFile(basepath + "_label"); len(raw) != 0 {
|
||||||
|
// Format the label from "Core 0" to "core_0"
|
||||||
|
label = strings.Join(strings.Split(strings.TrimSpace(strings.ToLower(string(raw))), " "), "_")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the name of the temperature you are reading
|
||||||
|
if raw, err = os.ReadFile(filepath.Join(directory, "name")); err != nil {
|
||||||
|
warns.Add(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
name := strings.TrimSpace(string(raw))
|
||||||
|
|
||||||
|
if label != "" {
|
||||||
|
name = name + "_" + label
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add discovered temperature sensor to the list
|
||||||
|
temperatures = append(temperatures, ExTemperature{
|
||||||
|
SensorKey: name,
|
||||||
|
Min: optionalValueReadFromFile(basepath+"_min") / hostTemperatureScale,
|
||||||
|
Lowest: optionalValueReadFromFile(basepath+"_lowest") / hostTemperatureScale,
|
||||||
|
Highest: optionalValueReadFromFile(basepath+"_highest") / hostTemperatureScale,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return temperatures, warns.Reference()
|
||||||
|
}
|
@ -5,6 +5,7 @@ package sensors
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -19,34 +20,20 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
||||||
var err error
|
|
||||||
|
|
||||||
var files []string
|
|
||||||
|
|
||||||
temperatures := make([]TemperatureStat, 0)
|
|
||||||
|
|
||||||
// Only the temp*_input file provides current temperature
|
|
||||||
// value in millidegree Celsius as reported by the temperature to the device:
|
|
||||||
// https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
|
|
||||||
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/temp*_input")); err != nil {
|
|
||||||
return temperatures, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(files) == 0 {
|
|
||||||
// CentOS has an intermediate /device directory:
|
|
||||||
// https://github.com/giampaolo/psutil/issues/971
|
|
||||||
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/device/temp*_input")); err != nil {
|
|
||||||
return temperatures, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var warns Warnings
|
var warns Warnings
|
||||||
|
|
||||||
|
files, err := getTemperatureFiles(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get tempreteure files, %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files
|
if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files
|
||||||
files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/thermal/thermal_zone*/"))
|
files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/thermal/thermal_zone*/"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return temperatures, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
temperatures := make([]TemperatureStat, 0, len(files))
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
// Get the name of the temperature you are reading
|
// Get the name of the temperature you are reading
|
||||||
name, err := os.ReadFile(filepath.Join(file, "type"))
|
name, err := os.ReadFile(filepath.Join(file, "type"))
|
||||||
@ -74,7 +61,7 @@ func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
|||||||
return temperatures, warns.Reference()
|
return temperatures, warns.Reference()
|
||||||
}
|
}
|
||||||
|
|
||||||
temperatures = make([]TemperatureStat, 0, len(files))
|
temperatures := make([]TemperatureStat, 0, len(files))
|
||||||
|
|
||||||
// example directory
|
// example directory
|
||||||
// device/ temp1_crit_alarm temp2_crit_alarm temp3_crit_alarm temp4_crit_alarm temp5_crit_alarm temp6_crit_alarm temp7_crit_alarm
|
// device/ temp1_crit_alarm temp2_crit_alarm temp3_crit_alarm temp4_crit_alarm temp5_crit_alarm temp6_crit_alarm temp7_crit_alarm
|
||||||
@ -139,6 +126,29 @@ func TemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) {
|
|||||||
return temperatures, warns.Reference()
|
return temperatures, warns.Reference()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTemperatureFiles(ctx context.Context) ([]string, error) {
|
||||||
|
var files []string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Only the temp*_input file provides current temperature
|
||||||
|
// value in millidegree Celsius as reported by the temperature to the device:
|
||||||
|
// https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
|
||||||
|
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/temp*_input")); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(files) == 0 {
|
||||||
|
// CentOS has an intermediate /device directory:
|
||||||
|
// https://github.com/giampaolo/psutil/issues/971
|
||||||
|
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/device/temp*_input")); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return files, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func optionalValueReadFromFile(filename string) float64 {
|
func optionalValueReadFromFile(filename string) float64 {
|
||||||
var raw []byte
|
var raw []byte
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user