Files
cmii-uav-watchdog-project/cmii-uav-watchdog-agent/host_info/disk_service.go
2025-03-18 14:40:03 +08:00

135 lines
3.7 KiB
Go

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
*/