//go:build linux // +build linux package main import ( "bufio" "os" "strings" "syscall" ) func readStorage() ([]StorageMetrics, error) { // For simplicity, report root mount. Can be extended to iterate mounts. var stat syscall.Statfs_t if err := syscall.Statfs("/", &stat); err != nil { return nil, err } total := stat.Blocks * uint64(stat.Bsize) free := stat.Bfree * uint64(stat.Bsize) used := total - free usedPercent := 0.0 if total > 0 { usedPercent = (float64(used) / float64(total)) * 100 } return []StorageMetrics{{ Mount: "/", TotalBytes: total, UsedBytes: used, FreeBytes: free, UsedPercent: round(usedPercent, 2), }}, nil } // readAllStorage 读取所有挂载的存储设备 func readAllStorage() ([]StorageMetrics, error) { storages := []StorageMetrics{} // 读取 /proc/mounts 获取所有挂载点 f, err := os.Open("/proc/mounts") if err != nil { return readStorage() // 降级到只读根目录 } defer f.Close() scanner := bufio.NewScanner(f) seen := make(map[string]bool) for scanner.Scan() { line := scanner.Text() fields := strings.Fields(line) if len(fields) < 3 { continue } device := fields[0] mountPoint := fields[1] fsType := fields[2] // 跳过虚拟文件系统 if strings.HasPrefix(device, "/dev/") == false { continue } // 跳过特殊文件系统类型 skipTypes := map[string]bool{ "tmpfs": true, "devtmpfs": true, "squashfs": true, "overlay": true, "aufs": true, "proc": true, "sysfs": true, "devpts": true, "cgroup": true, } if skipTypes[fsType] { continue } // 避免重复挂载点 if seen[mountPoint] { continue } seen[mountPoint] = true // 获取该挂载点的统计信息 var stat syscall.Statfs_t if err := syscall.Statfs(mountPoint, &stat); err != nil { continue } total := stat.Blocks * uint64(stat.Bsize) free := stat.Bfree * uint64(stat.Bsize) used := total - free usedPercent := 0.0 if total > 0 { usedPercent = (float64(used) / float64(total)) * 100 } // 只添加有容量的存储 if total > 0 { storages = append(storages, StorageMetrics{ Mount: mountPoint, TotalBytes: total, UsedBytes: used, FreeBytes: free, UsedPercent: round(usedPercent, 2), }) } } // 如果没有找到任何存储,至少返回根目录 if len(storages) == 0 { return readStorage() } return storages, nil }