bash_go_service/backend-service/pkg/machine/info.go

174 lines
3.9 KiB
Go

package machine
import (
"bash_go_service/shared/pkg/logger"
"bash_go_service/shared/pkg/utils"
"bufio"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
)
type Info struct {
Hostname string `json:"hostname"`
OS string `json:"os"`
Kernel string `json:"kernel"`
CPU string `json:"cpu"`
Memory string `json:"memory"`
GPU string `json:"gpu"`
ProductInfo utils.ProductInfo `json:"productInfo"`
}
func CollectMachineInfo() *Info {
productInfo, err := utils.GetProductInfo()
if err != nil {
logger.Debug("cannot get product info: %v", err)
}
return &Info{
Hostname: getHostname(),
OS: getOSInfo(),
Kernel: getKernelVersion(),
CPU: getCPUInfo(),
Memory: getMemoryInfo(),
GPU: getGPUInfo(),
ProductInfo: *productInfo,
}
}
func getGPUInfo() string {
if runtime.GOOS == "linux" {
cmd := exec.Command("lspci")
output, err := cmd.Output()
if err != nil {
return "unknown"
}
var gpus []string
scanner := bufio.NewScanner(strings.NewReader(string(output)))
for scanner.Scan() {
line := scanner.Text()
lineLower := strings.ToLower(line)
if strings.Contains(lineLower, "vga") || strings.Contains(lineLower, "3d") || strings.Contains(lineLower, "display") {
// Extract the detailed description of the GPU
parts := strings.SplitN(line, ": ", 2)
if len(parts) > 1 {
gpuInfo := strings.TrimSpace(parts[1])
gpus = append(gpus, gpuInfo)
} else {
gpus = append(gpus, strings.TrimSpace(line))
}
}
}
if len(gpus) > 0 {
return strings.Join(gpus, ", ")
}
}
return "unknown"
}
func getHostname() string {
name, err := os.Hostname()
if err != nil {
return "unknown"
}
return name
}
func getOSInfo() string {
if runtime.GOOS == "linux" {
out, err := exec.Command("lsb_release", "-d").Output()
if err == nil {
parts := strings.Split(string(out), ":")
if len(parts) > 1 {
return strings.TrimSpace(parts[1])
}
}
// 尝试读取 /etc/os-release
file, err := os.Open("/etc/os-release")
if err == nil {
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "PRETTY_NAME=") {
return strings.Trim(strings.TrimPrefix(line, "PRETTY_NAME="), "\"")
}
}
}
}
return runtime.GOOS
}
func getKernelVersion() string {
if runtime.GOOS == "linux" {
out, err := exec.Command("uname", "-r").Output()
if err == nil {
return strings.TrimSpace(string(out))
}
}
return "unknown"
}
func getCPUInfo() string {
if runtime.GOOS == "linux" {
out, err := exec.Command("lscpu").Output()
if err == nil {
return parseCPUInfo(string(out))
}
}
return runtime.GOARCH
}
func parseCPUInfo(output string) string {
scanner := bufio.NewScanner(strings.NewReader(output))
var model, cores string
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, "Model name:") {
model = strings.TrimSpace(strings.Split(line, ":")[1])
}
if strings.Contains(line, "CPU(s):") {
cores = strings.TrimSpace(strings.Split(line, ":")[1])
}
}
if model != "" && cores != "" {
return fmt.Sprintf("%s (%s cores)", model, cores)
}
return "unknown"
}
func getMemoryInfo() string {
if runtime.GOOS == "linux" {
file, err := os.Open("/proc/meminfo")
if err == nil {
defer file.Close()
scanner := bufio.NewScanner(file)
var totalMem, availMem string
for scanner.Scan() {
line := scanner.Text()
if strings.HasPrefix(line, "MemTotal:") {
totalMem = strings.TrimSpace(strings.TrimPrefix(line, "MemTotal:"))
} else if strings.HasPrefix(line, "MemAvailable:") {
availMem = strings.TrimSpace(strings.TrimPrefix(line, "MemAvailable:"))
}
if totalMem != "" && availMem != "" {
break
}
}
if totalMem != "" && availMem != "" {
return fmt.Sprintf("Total: %s, Available: %s", totalMem, availMem)
}
}
}
return "unknown"
}