版本封存
This commit is contained in:
@@ -1,163 +1,205 @@
|
||||
package services
|
||||
package host_info
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"cmii-uav-watchdog-common/models"
|
||||
"fmt"
|
||||
"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: "unknown",
|
||||
UUID: "unknown",
|
||||
ModelName: "unknown",
|
||||
Cores: 0,
|
||||
Architecture: "amd64",
|
||||
Flags: []string{},
|
||||
Hypervisor: "unknown",
|
||||
Virtualization: "unknown",
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
exePath = "/proc/self/exe"
|
||||
elfMagic = 0x7f
|
||||
elfMagicString = "ELF"
|
||||
eMachineOffset = 18
|
||||
)
|
||||
|
||||
// parseLine 解析单行 CPU 信息
|
||||
func parseLine(line string, cpuInfo *models.CPUInfo) {
|
||||
if strings.HasPrefix(line, "model name") {
|
||||
cpuInfo.ModelName = strings.TrimSpace(strings.Split(line, ":")[1])
|
||||
}
|
||||
}
|
||||
|
||||
// getCPUCores 通过 processor 行获取 CPU 核心数
|
||||
func getCPUCores() (int, error) {
|
||||
cores := 0
|
||||
file, err := os.Open("/proc/cpuinfo")
|
||||
if err != nil {
|
||||
return cores, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "processor") {
|
||||
cores++
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return cores, err
|
||||
}
|
||||
|
||||
return cores, nil
|
||||
}
|
||||
|
||||
// getCPUUUID 获取 CPU UUID
|
||||
func getCPUUUID() (string, error) {
|
||||
data, err := os.ReadFile("/sys/class/dmi/id/product_uuid")
|
||||
if err != nil {
|
||||
return "unknown", err
|
||||
}
|
||||
return strings.TrimSpace(string(data)), nil
|
||||
}
|
||||
|
||||
func getCPUArchitecture() string {
|
||||
cpuarch := "unknown"
|
||||
|
||||
// 打开当前进程的执行文件
|
||||
file, err := os.Open(exePath)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Error opening %s: %v\n", exePath, err)
|
||||
return cpuarch
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 读取前64个字节以获取 ELF 头部信息
|
||||
header := make([]byte, 64)
|
||||
if _, err := file.Read(header); err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Error reading header: %v\n", err)
|
||||
return cpuarch
|
||||
}
|
||||
|
||||
// 检查 ELF 文件标识
|
||||
if header[0] != elfMagic || string(header[1:4]) != elfMagicString {
|
||||
_, _ = fmt.Fprintln(os.Stderr, "File is not an ELF file")
|
||||
return cpuarch
|
||||
}
|
||||
|
||||
// 获取架构信息
|
||||
arch := header[eMachineOffset] // e_machine 字段的偏移量
|
||||
switch arch {
|
||||
case 0x02: // EM_386
|
||||
cpuarch = "x86(32-bit)"
|
||||
case 0x03: // EM_X86_64
|
||||
cpuarch = "x86_64(64-bit)"
|
||||
case 0x28: // EM_ARM
|
||||
cpuarch = "ARM"
|
||||
case 0x2A: // EM_ARM64
|
||||
cpuarch = "ARM64"
|
||||
case 0x08: // EM_MIPS
|
||||
cpuarch = "MIPS"
|
||||
default:
|
||||
cpuarch = "unknown architecture"
|
||||
}
|
||||
|
||||
return cpuarch
|
||||
}
|
||||
|
||||
// GetCPUInfo 获取 CPU 信息
|
||||
// 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
|
||||
// 打开/proc/cpuinfo文件
|
||||
file, err := os.Open("/proc/cpuinfo")
|
||||
if err != nil {
|
||||
fmt.Println("Error opening /proc/cpuinfo:", err)
|
||||
return cpuInfo // 返回默认值
|
||||
return cpuInfo, err
|
||||
}
|
||||
defer func() {
|
||||
if err := file.Close(); err != nil {
|
||||
fmt.Println("Error closing /proc/cpuinfo:", err)
|
||||
}
|
||||
}()
|
||||
defer file.Close()
|
||||
|
||||
// 使用scanner读取文件
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
// 处理的CPU核心数量
|
||||
coreCount := 1
|
||||
var flags []string
|
||||
|
||||
// 逐行读取并解析
|
||||
for scanner.Scan() {
|
||||
parseLine(scanner.Text(), &cpuInfo)
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Println("Error reading /proc/cpuinfo:", err)
|
||||
return cpuInfo // 返回默认值
|
||||
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, err := getCPUCores()
|
||||
// 如果没有从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 {
|
||||
fmt.Println("Error getting CPU cores:", err)
|
||||
} else {
|
||||
cpuInfo.Cores = cores
|
||||
return cpuInfo, err
|
||||
}
|
||||
|
||||
// 获取 CPU UUID
|
||||
uuid, err := getCPUUUID()
|
||||
if err != nil {
|
||||
fmt.Println("Error getting CPU UUID:", err)
|
||||
} else {
|
||||
cpuInfo.UUID = uuid
|
||||
// 解析输出
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cpuInfo.Architecture = getCPUArchitecture()
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
CPU模型名称: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz
|
||||
核心数量: 4
|
||||
架构信息: x86_64
|
||||
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user