初始化提交

This commit is contained in:
2025-12-14 15:25:31 +08:00
commit 4fa42f7115
48 changed files with 8718 additions and 0 deletions

View File

@@ -0,0 +1,182 @@
package main
import (
"bufio"
"errors"
"os"
"strconv"
"strings"
"time"
)
// readCPUUsage 读取CPU整体使用率
func readCPUUsage() (float64, error) {
idle1, total1, err := readCPUTicks()
if err != nil {
return 0, err
}
time.Sleep(250 * time.Millisecond)
idle2, total2, err := readCPUTicks()
if err != nil {
return 0, err
}
if total2 == total1 {
return 0, errors.New("cpu totals unchanged")
}
idleDelta := float64(idle2 - idle1)
totalDelta := float64(total2 - total1)
usage := (1.0 - idleDelta/totalDelta) * 100
if usage < 0 {
usage = 0
}
return usage, nil
}
// readCPUTicks 读取CPU的idle和total ticks
func readCPUTicks() (idle, total uint64, err error) {
f, err := os.Open("/proc/stat")
if err != nil {
return 0, 0, err
}
defer f.Close()
scanner := bufio.NewScanner(f)
if !scanner.Scan() {
return 0, 0, errors.New("failed to scan /proc/stat")
}
fields := strings.Fields(scanner.Text())
if len(fields) < 5 {
return 0, 0, errors.New("unexpected /proc/stat format")
}
// fields[0] is "cpu"
var vals []uint64
for _, f := range fields[1:] {
v, err := strconv.ParseUint(f, 10, 64)
if err != nil {
return 0, 0, err
}
vals = append(vals, v)
}
for _, v := range vals {
total += v
}
if len(vals) > 3 {
idle = vals[3] // idle time
// 注意:不包含 iowait因为 iowait 不算真正的空闲时间
// 如果系统有 iowait它会在 total 中,但不应该算作 idle
}
return idle, total, nil
}
// readPerCoreUsage 读取每个CPU核心的使用率
func readPerCoreUsage() []CoreUsage {
coreUsages := []CoreUsage{}
// 第一次读取
cores1 := readPerCoreTicks()
time.Sleep(100 * time.Millisecond) // 减少到100ms
// 第二次读取
cores2 := readPerCoreTicks()
for i := 0; i < len(cores1) && i < len(cores2); i++ {
idle1, total1 := cores1[i][0], cores1[i][1]
idle2, total2 := cores2[i][0], cores2[i][1]
if total2 == total1 {
continue
}
idleDelta := float64(idle2 - idle1)
totalDelta := float64(total2 - total1)
usage := (1.0 - idleDelta/totalDelta) * 100
if usage < 0 {
usage = 0
}
coreUsages = append(coreUsages, CoreUsage{
Core: i,
Percent: round(usage, 1),
})
}
return coreUsages
}
// readPerCoreTicks 读取每个CPU核心的ticks
func readPerCoreTicks() [][2]uint64 {
var result [][2]uint64
f, err := os.Open("/proc/stat")
if err != nil {
return result
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
if !strings.HasPrefix(line, "cpu") {
continue
}
if strings.HasPrefix(line, "cpu ") {
continue // 跳过总的cpu行
}
fields := strings.Fields(line)
if len(fields) < 5 {
continue
}
var vals []uint64
for _, f := range fields[1:] {
v, err := strconv.ParseUint(f, 10, 64)
if err != nil {
break
}
vals = append(vals, v)
}
if len(vals) < 5 {
continue
}
var total, idle uint64
for _, v := range vals {
total += v
}
idle = vals[3] // idle time only, not including iowait
result = append(result, [2]uint64{idle, total})
}
return result
}
// readCPUTemperature 读取CPU温度
func readCPUTemperature() float64 {
// 尝试从常见位置读取温度
paths := []string{
"/sys/class/thermal/thermal_zone0/temp",
"/sys/class/hwmon/hwmon0/temp1_input",
"/sys/class/hwmon/hwmon1/temp1_input",
}
for _, path := range paths {
if temp := readTempFromFile(path); temp > 0 {
return temp
}
}
return 0
}
// readLoadAverages 读取系统负载平均值
func readLoadAverages() []float64 {
line := readFirstLine("/proc/loadavg")
fields := strings.Fields(line)
res := make([]float64, 0, 3)
for i := 0; i < len(fields) && i < 3; i++ {
v, err := strconv.ParseFloat(fields[i], 64)
if err == nil {
res = append(res, v)
}
}
return res
}