This commit is contained in:
spiritlhl
2024-05-04 11:19:25 +00:00
parent 383f5c37b4
commit fd7b807ca4
9 changed files with 239 additions and 59 deletions

View File

@@ -8,6 +8,7 @@ import (
"strings" "strings"
"github.com/oneclickvirt/basics/system/model" "github.com/oneclickvirt/basics/system/model"
"github.com/oneclickvirt/basics/system/utils"
"github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/cpu"
) )
@@ -26,7 +27,9 @@ func checkCPUFeatureLinux(filename string, feature string) (string, bool) {
} }
func checkCPUFeature(filename string, feature string) (string, bool) { func checkCPUFeature(filename string, feature string) (string, bool) {
if runtime.GOOS == "linux" { if runtime.GOOS == "windows" {
return utils.CheckCPUFeatureWindows(filename, feature)
} else if runtime.GOOS == "linux" {
return checkCPUFeatureLinux(filename, feature) return checkCPUFeatureLinux(filename, feature)
} }
return "Unsupported OS", false return "Unsupported OS", false
@@ -65,5 +68,9 @@ func getCpuInfo(ret *model.SystemInfo, cpuType string) (*model.SystemInfo, error
if !st { if !st {
ret.CpuVAH, _ = checkCPUFeature(hypervFeature, "hypervisor") ret.CpuVAH, _ = checkCPUFeature(hypervFeature, "hypervisor")
} }
// 查询CPU的三缓
if runtime.GOOS == "windows" {
ret.CpuCache = utils.GetCpuCache()
}
return ret, nil return ret, nil
} }

View File

@@ -3,15 +3,15 @@ package system
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/libp2p/go-nat"
"github.com/oneclickvirt/basics/system/utils"
"github.com/shirou/gopsutil/host"
"runtime" "runtime"
"time" "time"
"github.com/libp2p/go-nat"
"github.com/shirou/gopsutil/host"
) )
func getHostInfo() (string, string, string, string, string, string, string, error) { func getHostInfo() (string, string, string, string, string, string, string, string, error) {
var Platform, Kernal, Arch, VmType, NatType string var Platform, Kernal, Arch, VmType, NatType, CurrentTimeZone string
var cachedBootTime time.Time var cachedBootTime time.Time
hi, err := host.Info() hi, err := host.Info()
if err != nil { if err != nil {
@@ -41,6 +41,10 @@ func getHostInfo() (string, string, string, string, string, string, string, erro
uptimeDuration -= time.Duration(hours) * time.Hour uptimeDuration -= time.Duration(hours) * time.Hour
minutes := int(uptimeDuration.Minutes()) minutes := int(uptimeDuration.Minutes())
uptimeFormatted := fmt.Sprintf("%d days, %02d hours, %02d minutes", days, hours, minutes) uptimeFormatted := fmt.Sprintf("%d days, %02d hours, %02d minutes", days, hours, minutes)
// windows 查询虚拟化类型 使用 wmic
if VmType == "" && runtime.GOOS == "windows" {
VmType = utils.CheckVMTypeWithWIMC()
}
// 查询NAT类型 // 查询NAT类型
ctx := context.Background() ctx := context.Background()
gateway, err := nat.DiscoverGateway(ctx) gateway, err := nat.DiscoverGateway(ctx)
@@ -48,5 +52,7 @@ func getHostInfo() (string, string, string, string, string, string, string, erro
natType := gateway.Type() natType := gateway.Type()
NatType = natType NatType = natType
} }
return cpuType, uptimeFormatted, Platform, Kernal, Arch, VmType, NatType, nil // 获取当前系统的本地时区
CurrentTimeZone = utils.GetTimeZone()
return cpuType, uptimeFormatted, Platform, Kernal, Arch, VmType, NatType, CurrentTimeZone, nil
} }

View File

@@ -2,37 +2,14 @@ package system
import ( import (
"bufio" "bufio"
"github.com/oneclickvirt/basics/system/utils"
"github.com/shirou/gopsutil/load"
"os" "os"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"github.com/shirou/gopsutil/load"
) )
// 获取系统负载信息
func getSystemLoad() (float64, float64, float64, error) {
var load1, load5, load15 float64
var err error
if runtime.GOOS == "linux" {
// 尝试从 /proc/loadavg 文件获取负载信息
load1, load5, load15, err = getLoadFromProc()
if err != nil {
load1, load5, load15 = 0, 0, 0
}
}
// 使用 gopsutil 获取负载
avg, err := load.Avg()
if err != nil {
load1, load5, load15 = 0, 0, 0
} else {
if avg.Load1 != 0 && avg.Load5 != 0 && avg.Load15 != 0 {
load1, load5, load15 = avg.Load1, avg.Load5, avg.Load15
}
}
return load1, load5, load15, nil
}
// getLoadFromProc 从 /proc/loadavg 文件中获取负载信息 // getLoadFromProc 从 /proc/loadavg 文件中获取负载信息
func getLoadFromProc() (float64, float64, float64, error) { func getLoadFromProc() (float64, float64, float64, error) {
file, err := os.Open("/proc/loadavg") file, err := os.Open("/proc/loadavg")
@@ -54,3 +31,30 @@ func getLoadFromProc() (float64, float64, float64, error) {
} }
return 0, 0, 0, nil return 0, 0, 0, nil
} }
// 获取系统负载信息
func getSystemLoad() (float64, float64, float64, error) {
var load1, load5, load15 float64
var err error
if runtime.GOOS == "linux" {
// 尝试从 /proc/loadavg 文件获取负载信息
load1, load5, load15, err = getLoadFromProc()
if err != nil {
load1, load5, load15 = 0, 0, 0
}
}
// 使用 gopsutil 获取负载
avg, err := load.Avg()
if err != nil {
load1, load5, load15 = 0, 0, 0
} else {
if avg.Load1 != 0 && avg.Load5 != 0 && avg.Load15 != 0 {
load1, load5, load15 = avg.Load1, avg.Load5, avg.Load15
}
}
// 有时候获取全为零时尝试使用 wmic 获取负载
if runtime.GOOS == "windows" && load1 == 0 && load5 == 0 && load15 == 0 {
load1 = utils.GetLoad1()
}
return load1, load5, load15, nil
}

View File

@@ -30,6 +30,7 @@ type SystemInfo struct {
Kernel string // 系统内核 Kernel string // 系统内核
Arch string // Arch string //
Uptime string // 正常运行时间 Uptime string // 正常运行时间
TimeZone string // 系统时区
VmType string // 虚拟化架构 VmType string // 虚拟化架构
Load string // load1 load2 load3 Load string // load1 load2 load3
NatType string // stun NatType string // stun
@@ -50,3 +51,7 @@ type Win32_ComputerSystem struct {
type Win32_OperatingSystem struct { type Win32_OperatingSystem struct {
BuildType string BuildType string
} }
type Win32_TimeZone struct {
Caption string
}

View File

@@ -3,6 +3,7 @@ package system
import ( import (
"fmt" "fmt"
"github.com/oneclickvirt/basics/system/model" "github.com/oneclickvirt/basics/system/model"
"github.com/oneclickvirt/basics/system/utils"
"strconv" "strconv"
) )
@@ -18,7 +19,7 @@ var (
func GetHost() *model.SystemInfo { func GetHost() *model.SystemInfo {
var ret = &model.SystemInfo{} var ret = &model.SystemInfo{}
// 系统信息查询 // 系统信息查询
cpuType, ret.Uptime, ret.Platform, ret.Kernel, ret.Arch, ret.VmType, ret.NatType, _ = getHostInfo() cpuType, ret.Uptime, ret.Platform, ret.Kernel, ret.Arch, ret.VmType, ret.NatType, ret.TimeZone, _ = getHostInfo()
// CPU信息查询 // CPU信息查询
ret, _ = getCpuInfo(ret, cpuType) ret, _ = getCpuInfo(ret, cpuType)
// 硬盘信息查询 // 硬盘信息查询
@@ -34,7 +35,7 @@ func GetHost() *model.SystemInfo {
strconv.FormatFloat(load5, 'f', 2, 64) + " / " + strconv.FormatFloat(load5, 'f', 2, 64) + " / " +
strconv.FormatFloat(load15, 'f', 2, 64) strconv.FormatFloat(load15, 'f', 2, 64)
// 获取TCP控制算法 // 获取TCP控制算法
ret.TcpAccelerationMethod = getTCPAccelerateStatus() ret.TcpAccelerationMethod = utils.GetTCPAccelerateStatus()
return ret return ret
} }
@@ -66,6 +67,7 @@ func GetSystemInfo() {
fmt.Println("Kernel :", ret.Kernel) fmt.Println("Kernel :", ret.Kernel)
} }
fmt.Println("Uptime :", ret.Uptime) fmt.Println("Uptime :", ret.Uptime)
fmt.Println("Current Time Zone :", ret.TimeZone)
fmt.Println("Load :", ret.Load) fmt.Println("Load :", ret.Load)
fmt.Println("VM Type :", ret.VmType) fmt.Println("VM Type :", ret.VmType)
fmt.Println("NAT Type :", ret.NatType) fmt.Println("NAT Type :", ret.NatType)
@@ -73,3 +75,8 @@ func GetSystemInfo() {
fmt.Println("Tcp Accelerate :", ret.TcpAccelerationMethod) fmt.Println("Tcp Accelerate :", ret.TcpAccelerationMethod)
} }
} }
// TODO
// NAT Type 在 linux 上查不到
// Boot Path 在 linux 上查询失败
// Cpu Cache 在 linux 上输出有问题,不能直接转换 string

View File

@@ -1,19 +0,0 @@
package system
import (
"bytes"
"os/exec"
)
// getTCPAccelerateStatus 查询TCP控制算法
func getTCPAccelerateStatus() string {
cmd := exec.Command("sysctl", "-n", "net.ipv4.tcp_congestion_control")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return ""
} else {
return out.String()
}
}

View File

@@ -1,6 +0,0 @@
package system
// getTCPAccelerateStatus 查询TCP控制算法
func getTCPAccelerateStatus() string {
return ""
}

View File

@@ -0,0 +1,44 @@
package utils
import (
"bytes"
"os/exec"
"time"
)
// GetCpuCache 查询CPU三缓
func GetCpuCache() string {
return ""
}
func CheckCPUFeatureWindows(subkey string, value string) (string, bool) {
return "", false
}
func CheckVMTypeWithWIMC() string {
return ""
}
func GetLoad1() float64 {
return 0
}
// GetTCPAccelerateStatus 查询TCP控制算法
func GetTCPAccelerateStatus() string {
cmd := exec.Command("sysctl", "-n", "net.ipv4.tcp_congestion_control")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return ""
} else {
return out.String()
}
}
// GetTimeZone 获取当前时区
func GetTimeZone() string {
local := time.Now().Location()
CurrentTimeZone := local.String()
return CurrentTimeZone
}

View File

@@ -0,0 +1,132 @@
package utils
import (
"fmt"
"math"
"strings"
"github.com/oneclickvirt/basics/system/model"
"github.com/yusufpapurcu/wmi"
"golang.org/x/sys/windows/registry"
)
// GetCpuCache 查询CPU三缓
func GetCpuCache() string {
var processors []model.Win32_Processor
err := wmi.Query("SELECT L2CacheSize, L3CacheSize FROM Win32_Processor", &processors)
if err == nil {
if len(processors) > 0 {
L1CacheSizeStr := "null"
L2CacheSize := processors[0].L2CacheSize
L3CacheSize := processors[0].L3CacheSize
var L2CacheSizeStr, L3CacheSizeStr string
if L2CacheSize >= 1024*1024 {
L2CacheSizeStr = fmt.Sprintf("%.2f GB", float64(L2CacheSize)/(1024*1024))
} else if L2CacheSize >= 1024 {
L2CacheSizeStr = fmt.Sprintf("%.2f MB", float64(L2CacheSize)/1024)
} else {
L2CacheSizeStr = fmt.Sprintf("%d KB", L2CacheSize)
}
if L3CacheSize >= 1024*1024 {
L3CacheSizeStr = fmt.Sprintf("%.2f GB", float64(L3CacheSize)/(1024*1024))
} else if L3CacheSize >= 1024 {
L3CacheSizeStr = fmt.Sprintf("%.2f MB", float64(L3CacheSize)/1024)
} else {
L3CacheSizeStr = fmt.Sprintf("%d KB", L3CacheSize)
}
return fmt.Sprintf("L1: %s / L2: %s / L3: %s", L1CacheSizeStr, L2CacheSizeStr, L3CacheSizeStr)
} else {
return ""
}
} else {
return ""
}
}
func CheckCPUFeatureWindows(subkey string, value string) (string, bool) {
k, err := registry.OpenKey(registry.LOCAL_MACHINE, subkey, registry.READ)
if err != nil {
return "❌ Disabled", false
}
defer k.Close()
val, _, err := k.GetStringValue(value)
if err != nil {
return "❌ Disabled", false
}
if strings.Contains(val, "1") {
return "✔️ Enabled", true
}
return "❌ Disabled", false
}
func CheckVMTypeWithWIMC() string {
var (
computers []model.Win32_ComputerSystem
operatingSystems []model.Win32_OperatingSystem
VmType string
)
err1 := wmi.Query("SELECT * FROM Win32_ComputerSystem", &computers)
err2 := wmi.Query("SELECT * FROM Win32_OperatingSystem", &operatingSystems)
if err1 == nil || err2 == nil {
if len(computers) > 0 || len(operatingSystems) > 0 {
switch {
case (len(computers) > 0 && strings.Contains(computers[0].SystemType, "Multiprocessor Free")) ||
(len(operatingSystems) > 0 && strings.Contains(operatingSystems[0].BuildType, "Multiprocessor Free")):
VmType = "Physical-Machine" + "(" + "Multiprocessor Free" + ")"
case (len(computers) > 0 && strings.Contains(computers[0].SystemType, "Virtual Machine")) ||
(len(operatingSystems) > 0 && strings.Contains(operatingSystems[0].BuildType, "Virtual Machine")):
VmType = "Hyper-V" + "(" + "Virtual Machine" + ")"
case (len(computers) > 0 && strings.Contains(computers[0].SystemType, "VMware")) ||
(len(operatingSystems) > 0 && strings.Contains(operatingSystems[0].BuildType, "VMware")):
VmType = "VMware"
default:
if len(computers) > 0 && len(operatingSystems) > 0 {
VmType = computers[0].SystemType + "(" + operatingSystems[0].BuildType + ")"
} else if len(computers) > 0 {
VmType = computers[0].SystemType
} else if len(operatingSystems) > 0 {
VmType = operatingSystems[0].BuildType
}
}
}
}
return VmType
}
func GetLoad1() float64 {
var load1 float64
type Win32_Processor struct {
LoadPercentage uint16
NumberOfCores uint32
}
var processors []Win32_Processor
query := "SELECT LoadPercentage, NumberOfCores FROM Win32_Processor"
err := wmi.Query(query, &processors)
if err == nil {
for _, processor := range processors {
tempLoad := float64(processor.LoadPercentage) / float64(processor.NumberOfCores)
load1 = math.Round(tempLoad*100) / 100
}
}
return load1
}
// GetTCPAccelerateStatus 查询TCP控制算法
func GetTCPAccelerateStatus() string {
return ""
}
// GetTimeZone 获取当前时区
func GetTimeZone() string {
var timezone []model.Win32_TimeZone
err := wmi.Query("SELECT * FROM Win32_TimeZone", &timezone)
if err == nil {
if len(timezone) > 0 {
return timezone[0].Caption
} else {
return ""
}
} else {
return ""
}
}