gopsutilで温度情報を取得する(OS別)

この記事は、Infocom Advent Calendar 2021 7日目の記事です。

qiita.com

あまり業務とは関係ないのですが、shirou/gopsutilを使ってサーバ情報を表示するアプリを作っている過程で、各種温度情報が取れるのが分かりました。 ただし、MacLinuxWindowsでそれぞれ違っていて、試行錯誤したので記録に残しておきます。

今年のアドベントカレンダーは全然埋まってないので、皆さん頑張ってw

Mac

開発をしているのがMacなのでまずはMacでとれるようにします。
個人で使っているMacbook Air(Intel) Mojaveです。

package main

import (
    "fmt"
    "os"

    "github.com/shirou/gopsutil/v3/host"
)

func main() {
    h1, h2, h3, _ := host.PlatformInformation()
    fmt.Println(h1, h2, h3)
    t, err := host.SensorsTemperatures()
    if err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
    }
    for _, v := range t {
        fmt.Printf("sensorKey: %s, temperature: %2.0f, sensorHigh: %2.0f, sensorCritical: %2.0f\n", v.SensorKey, v.Temperature, v.High, v.Critical)
    }
}

実行してみます。

$ go run main.go
darwin Standalone Workstation 11.5.1
sensorKey: TA0P, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TA1P, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TC0D, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TC0H, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TC0P, temperature: 58, sensorHigh:  0, sensorCritical:  0
sensorKey: TB0T, temperature: 36, sensorHigh:  0, sensorCritical:  0
sensorKey: TB1T, temperature: 36, sensorHigh:  0, sensorCritical:  0
sensorKey: TB2T, temperature: 32, sensorHigh:  0, sensorCritical:  0
sensorKey: TB3T, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TG0D, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TG0H, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TG0P, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TH0P, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TM0S, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TM0P, temperature: 54, sensorHigh:  0, sensorCritical:  0
sensorKey: TN0H, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TN0D, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TN0P, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TI0P, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TI1P, temperature:  0, sensorHigh:  0, sensorCritical:  0
sensorKey: TW0P, temperature: 49, sensorHigh:  0, sensorCritical:  0

TA0Pとかは、smc_darwin.hで定義されているようです。

https://github.com/shirou/gopsutil/blob/master/v3/host/smc_darwin.h

#define AMBIENT_AIR_0          "TA0P"
#define AMBIENT_AIR_1          "TA1P"
#define CPU_0_DIODE            "TC0D"
#define CPU_0_HEATSINK         "TC0H"
#define CPU_0_PROXIMITY        "TC0P"
#define ENCLOSURE_BASE_0       "TB0T"
#define ENCLOSURE_BASE_1       "TB1T"
#define ENCLOSURE_BASE_2       "TB2T"
#define ENCLOSURE_BASE_3       "TB3T"
#define GPU_0_DIODE            "TG0D"
#define GPU_0_HEATSINK         "TG0H"
#define GPU_0_PROXIMITY        "TG0P"
#define HARD_DRIVE_BAY         "TH0P"
#define MEMORY_SLOT_0          "TM0S"
#define MEMORY_SLOTS_PROXIMITY "TM0P"
#define NORTHBRIDGE            "TN0H"
#define NORTHBRIDGE_DIODE      "TN0D"
#define NORTHBRIDGE_PROXIMITY  "TN0P"
#define THUNDERBOLT_0          "TI0P"
#define THUNDERBOLT_1          "TI1P"
#define WIRELESS_MODULE        "TW0P"

CPU関係では、TC0DとTC0Hは取れておらず、TC0Pだけ取れているようです。
PROXIMITYは近い・近接的な意味のようなのでCPU温度を見るならとりあえずTC0Pでよいのかなと思いました。

Windows

お仕事ではWindowsサーバを使うのでこちらも取得してみます。

とりあえず同じコードを実行してみます。

C:\home\gozu\go\src\github.com\gozuk16\cputemp>go run main.go
Microsoft Windows 10 Pro Standalone Workstation 10.0.19042 Build 19042
例外が発生しました。 (アクセスは拒否されました )
exit status 1

どうやらWindowsでは管理者権限が必要みたいですね。
管理者権限で実行してみます。

C:\home\gozu\go\src\github.com\gozuk16\cputemp>go run main.go
Microsoft Windows 10 Pro Standalone Workstation 10.0.19043 Build 19043
sensorKey: ACPI\ThermalZone\THM0_0, temperature: 40, sensorHigh:  0, sensorCritical:  0

ACPI\ThermalZone\THM0_0というのが1つだけ取れました。

これはWMIの情報のようです。wmicで確認のため同じものを取得してみます。 (この場合も管理者権限が必要です)

> wmic /namespace:\\root\wmi PATH MSAcpi_ThermalZoneTemperature get CurrentTemperature
Temperature
CurrentTemperature
3132

3132度???
いやいやそんなわけない。
これはケルビンという値を10倍したものが取れるものらしい。
ケルビンとは絶対温度の事で、摂氏を求めるには「ケルビン - 273.16」とすればよい
つまり、摂氏に直すと 3132 / 10 - 273.16 = 40.04 となります。
どうやらプログラムで取った値は正しそうですね。

管理者権限が必要なのは面倒くさいなぁ。

Linux

VMじゃない実機のLinuxだとラズパイがあるのでやってみました。

Raspberry Pi OS 64bit版にしてあるのですが、どうやらaptで入るGoは1.11という古いバージョンなのでダウンロードして入れます。

$ wget https://golang.org/dl/go1.16.7.linux-arm64.tar.gz
$ sudo tar -C /usr/local -xzf go1.16.7.linux-arm64.tar.gz
$ vi .bashrc
# ↓を追加
export PATH=$PATH:/usr/local/go/bin
$ . .bashrc
$ go version
go version go1.16.7 linux/arm64

同じものを実行します。

$ go run main.go
raspbian debian 10.10
sensorKey: cpu_thermal, temperature: 62 sensorHigh:  0, sensorCritical:  0

cpu_thermalというのが1つ取れました。
確認のためコマンドでたたいてみます。

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

62322度な訳は無いw
これは1000倍で取れるそうなのであってます。