package services import ( "cmii-uav-watchdog-common/models" "fmt" "strconv" "strings" "syscall" ) // GetDiskInfo retrieves disk information similar to df -Th. func GetDiskInfo() []models.DiskInfo { var diskInfos []models.DiskInfo // Read /proc/mounts to get mounted filesystems mountsData, err := readFileWithWarning("/proc/mounts") if err != nil { return diskInfos } mounts := strings.Split(string(mountsData), "\n") // Read /proc/partitions to get physical disks partitionsData, err := readFileWithWarning("/proc/partitions") if err != nil { return diskInfos } partitions := strings.Split(string(partitionsData), "\n") physicalDevices := make(map[string]uint64) // Map physical devices to their sizes for _, line := range partitions { fields := strings.Fields(line) if len(fields) < 4 { continue } device := fields[3] // The device name is in the 4th column size, err := strconv.ParseUint(fields[2], 10, 64) // 读取大小 if err != nil { continue } physicalDevices[device] = size * 1024 // 转换为字节 } for _, mount := range mounts { if mount == "" { continue } fields := strings.Fields(mount) if len(fields) < 3 { continue } logicalDevice := fields[0] // 逻辑分区设备名 mountPoint := fields[1] // 挂载点 fstype := fields[2] // 文件系统类型 // Skip NFS mounts if fstype == "nfs" { continue } // Skip overlay mounts if fstype == "overlay" { continue } // Get disk usage information using stat var stat syscall.Statfs_t if err := syscall.Statfs(mountPoint, &stat); err != nil { fmt.Printf("Warning: error getting statfs for %s: %v\n", mountPoint, err) continue } // Calculate total, used, and available space total := stat.Blocks * uint64(stat.Bsize) available := stat.Bavail * uint64(stat.Bsize) used := total - available // Skip if size is 0 if total == 0 { continue } // Calculate percentage used usePercent := "0%" if total > 0 { usePercent = fmt.Sprintf("%.1f%%", float64(used)/float64(total)*100) } // Determine the physical device and its size physicalDevice := "" physicalSize := uint64(0) // Check if the logical device is a partition (e.g., /dev/sda1) if strings.HasPrefix(logicalDevice, "/dev/") { // Get the corresponding physical device (e.g., /dev/sda) physicalDevice = strings.TrimSuffix(logicalDevice, "1") // 假设逻辑分区是 /dev/sda1 if size, exists := physicalDevices[physicalDevice]; exists { physicalSize = size } } // If not found, use the logical device as the physical device if physicalDevice == "" || physicalSize == 0 { physicalDevice = logicalDevice if size, exists := physicalDevices[physicalDevice]; exists { physicalSize = size } } diskInfos = append(diskInfos, models.DiskInfo{ Device: logicalDevice, // 设置逻辑分区的设备名称 Filesystem: logicalDevice, // 逻辑分区 Type: fstype, // 文件系统类型 Size: total, // 总大小 Used: used, // 已用空间 Available: available, // 可用空间 UsePercent: usePercent, // 使用百分比 MountPoint: mountPoint, // 挂载点 PhysicalDevice: physicalDevice, // 物理设备名称 PhysicalSize: physicalSize, // 物理盘大小 }) } return diskInfos } /* Device: sda, Total: 500107862016 bytes, Used: 250000000000 bytes, Available: 200000000000 bytes Device: sdb, Total: 400107862016 bytes, Used: 150000000000 bytes, Available: 250000000000 bytes Device: sdc, Total: 100107862016 bytes, Used: 50000000000 bytes, Available: 50000000000 bytes Device: unknown, Total: 0 bytes, Used: 0 bytes, Available: 0 bytes */