206 lines
4.7 KiB
Go
206 lines
4.7 KiB
Go
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
|
||
}
|