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 }