From 37b4d23873dfb6d49ea1b77a0f0ef4b27ccf8eb9 Mon Sep 17 00:00:00 2001 From: spiritlhl <103393591+spiritLHLS@users.noreply.github.com> Date: Thu, 10 Jul 2025 06:21:13 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=80=82=E9=85=8DMACOS=E5=A4=9A?= =?UTF-8?q?=E7=9B=98=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- system/disk.go | 184 ++++++++++++++++++++++++----------- system/gpu/gpu.go | 2 - system/gpu/gpu_darwin.go | 3 - system/gpu/gpu_darwin_cgo.go | 3 - 4 files changed, 127 insertions(+), 65 deletions(-) diff --git a/system/disk.go b/system/disk.go index a64cb7a..4d8b857 100644 --- a/system/disk.go +++ b/system/disk.go @@ -33,51 +33,59 @@ func getDiskInfo() ([]string, []string, []string, string, error) { var currentDiskInfo *DiskSingelInfo // macOS 特殊适配 if runtime.GOOS == "darwin" { - // 获取所有APFS卷的挂载点 - mountPoints := getMacOSMountPoints() - for _, mountPoint := range mountPoints { - cmd := exec.Command("df", "-k", mountPoint) - output, err := cmd.Output() - if err != nil { - continue + // 获取 APFS 容器信息 + containers := getMacOSAPFSContainers() + for _, container := range containers { + if container.TotalBytes >= 200*1024*1024*1024 { + diskInfos = append(diskInfos, container) } - lines := strings.Split(string(output), "\n") - if len(lines) >= 2 { - fields := strings.Fields(lines[1]) - if len(fields) >= 6 { - totalKB, err1 := strconv.ParseUint(fields[1], 10, 64) - usedKB, err2 := strconv.ParseUint(fields[2], 10, 64) - if err1 == nil && err2 == nil { - totalBytes := totalKB * 1024 - usedBytes := usedKB * 1024 - diskTotalGB := float64(totalBytes) / (1024 * 1024 * 1024) - diskUsageGB := float64(usedBytes) / (1024 * 1024 * 1024) - var diskTotalStr, diskUsageStr string - if diskTotalGB < 1 { - diskTotalStr = strconv.FormatFloat(diskTotalGB*1024, 'f', 2, 64) + " MB" - } else { - diskTotalStr = strconv.FormatFloat(diskTotalGB, 'f', 2, 64) + " GB" - } - if diskUsageGB < 1 { - diskUsageStr = strconv.FormatFloat(diskUsageGB*1024, 'f', 2, 64) + " MB" - } else { - diskUsageStr = strconv.FormatFloat(diskUsageGB, 'f', 2, 64) + " GB" - } - percentage := float64(usedBytes) / float64(totalBytes) * 100 - percentageStr := strconv.FormatFloat(percentage, 'f', 1, 64) + "%%" - diskInfo := DiskSingelInfo{ - TotalStr: diskTotalStr, - UsageStr: diskUsageStr, - PercentageStr: percentageStr, - BootPath: fields[0], - TotalBytes: totalBytes, - } - if mountPoint == "/" { + // 检查是否包含根分区 + if container.BootPath != "" && (strings.Contains(container.BootPath, "disk3") || container.BootPath == "/" || currentDiskInfo == nil) { + bootPath = container.BootPath + currentDiskInfo = &container + } + } + // 如果没有找到包含根分区的容器,使用 df 命令作为fallback + if currentDiskInfo == nil { + cmd := exec.Command("df", "-k", "/") + output, err := cmd.Output() + if err == nil { + lines := strings.Split(string(output), "\n") + if len(lines) >= 2 { + fields := strings.Fields(lines[1]) + if len(fields) >= 6 { + totalKB, err1 := strconv.ParseUint(fields[1], 10, 64) + usedKB, err2 := strconv.ParseUint(fields[2], 10, 64) + if err1 == nil && err2 == nil { + totalBytes := totalKB * 1024 + usedBytes := usedKB * 1024 + diskTotalGB := float64(totalBytes) / (1024 * 1024 * 1024) + diskUsageGB := float64(usedBytes) / (1024 * 1024 * 1024) + var diskTotalStr, diskUsageStr string + if diskTotalGB < 1 { + diskTotalStr = strconv.FormatFloat(diskTotalGB*1024, 'f', 2, 64) + " MB" + } else { + diskTotalStr = strconv.FormatFloat(diskTotalGB, 'f', 2, 64) + " GB" + } + if diskUsageGB < 1 { + diskUsageStr = strconv.FormatFloat(diskUsageGB*1024, 'f', 2, 64) + " MB" + } else { + diskUsageStr = strconv.FormatFloat(diskUsageGB, 'f', 2, 64) + " GB" + } + percentage := float64(usedBytes) / float64(totalBytes) * 100 + percentageStr := strconv.FormatFloat(percentage, 'f', 1, 64) + "%%" + diskInfo := DiskSingelInfo{ + TotalStr: diskTotalStr, + UsageStr: diskUsageStr, + PercentageStr: percentageStr, + BootPath: fields[0], + TotalBytes: totalBytes, + } bootPath = fields[0] currentDiskInfo = &diskInfo - } - if totalBytes >= 200*1024*1024*1024 { - diskInfos = append(diskInfos, diskInfo) + if totalBytes >= 200*1024*1024*1024 { + diskInfos = append(diskInfos, diskInfo) + } } } } @@ -288,30 +296,92 @@ func getDiskInfo() ([]string, []string, []string, string, error) { return diskTotalStrs, diskUsageStrs, percentageStrs, bootPath, nil } -// getMacOSMountPoints 获取macOS所有APFS卷的挂载点 -func getMacOSMountPoints() []string { - var mountPoints []string - mountPoints = append(mountPoints, "/") - cmd := exec.Command("diskutil", "list") +// getMacOSAPFSContainers 获取macOS APFS容器信息 +func getMacOSAPFSContainers() []DiskSingelInfo { + var containers []DiskSingelInfo + cmd := exec.Command("diskutil", "apfs", "list") output, err := cmd.Output() if err != nil { - return mountPoints + return containers } lines := strings.Split(string(output), "\n") + var currentContainer *DiskSingelInfo + var totalBytes, usedBytes uint64 + var containerDisk string for _, line := range lines { - if strings.Contains(line, "APFS Volume") && !strings.Contains(line, "Preboot") && !strings.Contains(line, "Recovery") && !strings.Contains(line, "VM") { + line = strings.TrimSpace(line) + if strings.Contains(line, "Container disk") { + if currentContainer != nil { + containers = append(containers, *currentContainer) + } fields := strings.Fields(line) - if len(fields) >= 4 { - volumeName := fields[3] - if volumeName == "Macintosh" || volumeName == "Data" { - continue + if len(fields) >= 2 { + containerDisk = fields[1] + currentContainer = &DiskSingelInfo{ + BootPath: containerDisk, } - mountPoint := "/Volumes/" + volumeName - mountPoints = append(mountPoints, mountPoint) + } + } else if currentContainer != nil { + if strings.Contains(line, "Size (Capacity Ceiling):") { + parts := strings.Split(line, ":") + if len(parts) >= 2 { + sizeStr := strings.TrimSpace(parts[1]) + if strings.Contains(sizeStr, " B ") { + sizeFields := strings.Fields(sizeStr) + if len(sizeFields) >= 1 { + if size, err := strconv.ParseUint(sizeFields[0], 10, 64); err == nil { + totalBytes = size + } + } + } + } + } + if strings.Contains(line, "Capacity In Use By Volumes:") { + parts := strings.Split(line, ":") + if len(parts) >= 2 { + usedStr := strings.TrimSpace(parts[1]) + if strings.Contains(usedStr, " B ") { + usedFields := strings.Fields(usedStr) + if len(usedFields) >= 1 { + if used, err := strconv.ParseUint(usedFields[0], 10, 64); err == nil { + usedBytes = used + } + } + } + } + } + if strings.Contains(line, "Snapshot Mount Point:") && strings.Contains(line, "/") { + currentContainer.BootPath = containerDisk } } + if currentContainer != nil && totalBytes > 0 && usedBytes > 0 { + diskTotalGB := float64(totalBytes) / (1024 * 1024 * 1024) + diskUsageGB := float64(usedBytes) / (1024 * 1024 * 1024) + var diskTotalStr, diskUsageStr string + if diskTotalGB < 1 { + diskTotalStr = strconv.FormatFloat(diskTotalGB*1024, 'f', 2, 64) + " MB" + } else { + diskTotalStr = strconv.FormatFloat(diskTotalGB, 'f', 2, 64) + " GB" + } + if diskUsageGB < 1 { + diskUsageStr = strconv.FormatFloat(diskUsageGB*1024, 'f', 2, 64) + " MB" + } else { + diskUsageStr = strconv.FormatFloat(diskUsageGB, 'f', 2, 64) + " GB" + } + percentage := float64(usedBytes) / float64(totalBytes) * 100 + percentageStr := strconv.FormatFloat(percentage, 'f', 1, 64) + "%%" + currentContainer.TotalStr = diskTotalStr + currentContainer.UsageStr = diskUsageStr + currentContainer.PercentageStr = percentageStr + currentContainer.TotalBytes = totalBytes + totalBytes = 0 + usedBytes = 0 + } } - return mountPoints + if currentContainer != nil { + containers = append(containers, *currentContainer) + } + return containers } // parseSize 解析尺寸字符串为字节数 @@ -442,4 +512,4 @@ func isListContainsStr(list []string, str string) bool { } } return false -} \ No newline at end of file +} diff --git a/system/gpu/gpu.go b/system/gpu/gpu.go index c1d9355..0ba4eea 100644 --- a/system/gpu/gpu.go +++ b/system/gpu/gpu.go @@ -15,13 +15,11 @@ func GetGPUModel() ([]string, error) { if err != nil { return nil, err } - for _, card := range gi.GraphicsCards { if card.DeviceInfo == nil { return nil, errors.New("Cannot find device info") } gpuModel = append(gpuModel, card.DeviceInfo.Product.Name) } - return gpuModel, nil } diff --git a/system/gpu/gpu_darwin.go b/system/gpu/gpu_darwin.go index 2664f8d..f94d7f3 100644 --- a/system/gpu/gpu_darwin.go +++ b/system/gpu/gpu_darwin.go @@ -13,7 +13,6 @@ func extractGPUInfo(cmd *exec.Cmd) ([]string, error) { if err != nil { return nil, err } - re := regexp.MustCompile(`"model"\s*=\s*["<]?"([^">]+)"[">]?`) matches := re.FindAllSubmatch(gi, -1) var modelNames []string @@ -29,7 +28,6 @@ func GetGPUModel() ([]string, error) { vendorNames := []string{ "AMD", "Intel", "Nvidia", "Apple", } - ioreg := exec.Command("ioreg", "-rd1", "-c", "IOAccelerator") gi, err := extractGPUInfo(ioreg) if err != nil || len(gi) == 0 { @@ -39,7 +37,6 @@ func GetGPUModel() ([]string, error) { return nil, err } } - var gpuModel []string for _, model := range gi { for _, vendor := range vendorNames { diff --git a/system/gpu/gpu_darwin_cgo.go b/system/gpu/gpu_darwin_cgo.go index 1c4cc61..a074270 100644 --- a/system/gpu/gpu_darwin_cgo.go +++ b/system/gpu/gpu_darwin_cgo.go @@ -43,15 +43,12 @@ func GetGPUModel() ([]string, error) { vendorNames := []string{ "AMD", "Intel", "Nvidia", "Apple", } - key := C.CString("model") defer C.free(unsafe.Pointer(key)) - gi, err := extractGPUInfo(key) if err != nil { return nil, err } - var gpuModel []string for _, model := range gi { for _, vendor := range vendorNames {