Files
2025-12-06 11:26:05 +08:00

206 lines
4.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package host_info
import (
"bufio"
"cmii-uav-watchdog-common/models"
"cmii-uav-watchdog-common/wdd_log"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
)
// NewCPUInfo 创建一个默认的 CPUInfo
func NewCPUInfo() models.CPUInfo {
return models.CPUInfo{
ModelName: "unknown",
Cores: 0,
Architecture: "amd64",
Flags: []string{},
Hypervisor: "unknown",
Virtualization: "unknown",
}
}
// GetCPUInfo 获取CPU信息
// 返回CPU信息结构体
func GetCPUInfo() models.CPUInfo {
wdd_log.Debug("开始获取CPU信息")
// 首先尝试从/proc/cpuinfo文件中读取信息
cpuInfo, err := getCPUInfoFromProc()
if err == nil {
wdd_log.Debug("成功从/proc/cpuinfo获取CPU信息")
return cpuInfo
}
// 如果从文件获取失败尝试使用lscpu命令
wdd_log.Warn("从/proc/cpuinfo获取CPU信息失败: %s尝试使用lscpu命令", err.Error())
cpuInfo, err = getCPUInfoFromLscpu()
if err == nil {
wdd_log.Debug("成功从lscpu命令获取CPU信息")
return cpuInfo
}
// 如果都失败使用runtime包获取基本信息
wdd_log.Warn("从lscpu获取CPU信息失败: %s使用runtime包获取基本信息", err.Error())
return getFallbackCPUInfo()
}
// getCPUInfoFromProc 从/proc/cpuinfo文件中读取CPU信息
// 返回CPU信息结构体和可能的错误
func getCPUInfoFromProc() (models.CPUInfo, error) {
wdd_log.Debug("尝试从/proc/cpuinfo读取CPU信息")
// 创建默认的CPU信息结构体
cpuInfo := NewCPUInfo()
// 打开/proc/cpuinfo文件
file, err := os.Open("/proc/cpuinfo")
if err != nil {
return cpuInfo, err
}
defer file.Close()
// 使用scanner读取文件
scanner := bufio.NewScanner(file)
// 处理的CPU核心数量
coreCount := 1
var flags []string
// 逐行读取并解析
for scanner.Scan() {
line := scanner.Text()
parts := strings.Split(line, ":")
if len(parts) < 2 {
continue
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
switch key {
case "processor":
// 计数处理器核心数量
coreCount++
case "model name":
// 获取CPU型号名称
cpuInfo.ModelName = value
// 提取频率信息(如果包含)
if strings.Contains(value, "@") {
freqParts := strings.Split(value, "@")
if len(freqParts) > 1 {
cpuInfo.Frequency = strings.TrimSpace(freqParts[1])
}
}
case "flags":
// 获取CPU标志
flags = strings.Fields(value)
case "cpu cores":
// 获取每个物理CPU的核心数
cores, err := strconv.Atoi(value)
if err == nil && cores > 0 {
cpuInfo.Cores = cores
}
}
}
// 如果没有从cpu cores字段获取到核心数使用处理器计数
if cpuInfo.Cores == 0 && coreCount > 0 {
cpuInfo.Cores = coreCount
}
// 设置CPU标志
cpuInfo.Flags = flags
// 检测虚拟化相关信息
for _, flag := range flags {
if flag == "vmx" {
cpuInfo.Virtualization = "vmx"
} else if flag == "svm" {
cpuInfo.Virtualization = "svm"
} else if flag == "hypervisor" {
cpuInfo.Hypervisor = "present"
}
}
// 设置架构
cpuInfo.Architecture = runtime.GOARCH
return cpuInfo, nil
}
// getCPUInfoFromLscpu 使用lscpu命令获取CPU信息
// 返回CPU信息结构体和可能的错误
func getCPUInfoFromLscpu() (models.CPUInfo, error) {
wdd_log.Debug("尝试使用lscpu命令获取CPU信息")
// 创建默认的CPU信息结构体
cpuInfo := NewCPUInfo()
// 执行lscpu命令
cmd := exec.Command("lscpu")
output, err := cmd.Output()
if err != nil {
return cpuInfo, err
}
// 解析输出
lines := strings.Split(string(output), "\n")
for _, line := range lines {
parts := strings.Split(line, ":")
if len(parts) < 2 {
continue
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
switch key {
case "Model name":
cpuInfo.ModelName = value
// 提取频率信息(如果包含)
if strings.Contains(value, "@") {
freqParts := strings.Split(value, "@")
if len(freqParts) > 1 {
cpuInfo.Frequency = strings.TrimSpace(freqParts[1])
}
}
case "Architecture":
cpuInfo.Architecture = value
case "CPU(s)":
cores, err := strconv.Atoi(value)
if err == nil {
cpuInfo.Cores = cores
}
case "Flags":
cpuInfo.Flags = strings.Fields(value)
case "Hypervisor vendor":
cpuInfo.Hypervisor = value
case "Virtualization":
cpuInfo.Virtualization = value
case "CPU MHz":
if cpuInfo.Frequency == "" {
cpuInfo.Frequency = value + " MHz"
}
}
}
return cpuInfo, nil
}
// getFallbackCPUInfo 使用runtime包获取基本CPU信息
// 返回CPU信息结构体
func getFallbackCPUInfo() models.CPUInfo {
wdd_log.Debug("使用runtime包获取基本CPU信息")
cpuInfo := NewCPUInfo()
cpuInfo.Cores = runtime.NumCPU()
cpuInfo.Architecture = runtime.GOARCH
return cpuInfo
}