diff --git a/pkg/agent/collector/disk.go b/pkg/agent/collector/disk.go index ec61350..dd9b561 100644 --- a/pkg/agent/collector/disk.go +++ b/pkg/agent/collector/disk.go @@ -1,11 +1,24 @@ package collector import ( + "strings" + "github.com/dushixiang/pika/internal/protocol" "github.com/dushixiang/pika/pkg/agent/config" "github.com/shirou/gopsutil/v4/disk" ) +// 不以 /dev/ 开头但仍是真实存储的文件系统类型 +var realFSTypes = map[string]bool{ + "nfs": true, + "nfs4": true, + "cifs": true, + "smbfs": true, + "zfs": true, + "glusterfs": true, + "cephfs": true, +} + // DiskCollector 磁盘监控采集器 type DiskCollector struct { config *config.Config @@ -18,6 +31,43 @@ func NewDiskCollector(cfg *config.Config) *DiskCollector { } } +// isRealDisk 判断是否为真实存储设备 +func isRealDisk(device, fstype string) bool { + // Windows 盘符 + if len(device) == 2 && device[1] == ':' { + return true + } + // Unix 块设备 + if strings.HasPrefix(device, "/dev/") { + return true + } + // 网络/集群存储 + return realFSTypes[fstype] +} + +// macOS APFS 容器内与数据卷共享物理空间的系统辅助卷 +var macosSystemVolumes = map[string]bool{ + "Preboot": true, + "VM": true, + "Update": true, + "xarts": true, + "iSCPreboot": true, + "Hardware": true, +} + +// isMacOSRedundant 判断是否为 macOS APFS 冗余系统卷 +func isMacOSRedundant(mountPoint, fstype string) bool { + if fstype != "apfs" { + return false + } + const prefix = "/System/Volumes/" + if !strings.HasPrefix(mountPoint, prefix) { + return false + } + volumeName := strings.TrimPrefix(mountPoint, prefix) + return macosSystemVolumes[volumeName] +} + // Collect 采集磁盘数据 // 只采集配置的 DiskInclude 白名单中的挂载点 func (d *DiskCollector) Collect() ([]protocol.DiskData, error) { @@ -28,6 +78,16 @@ func (d *DiskCollector) Collect() ([]protocol.DiskData, error) { var diskDataList []protocol.DiskData for _, partition := range partitions { + // 跳过虚拟文件系统 + if !isRealDisk(partition.Device, partition.Fstype) { + continue + } + + // 跳过 macOS APFS 冗余系统卷(与 Data 共享物理空间) + if isMacOSRedundant(partition.Mountpoint, partition.Fstype) { + continue + } + // 检查是否在白名单中 if !d.config.ShouldIncludeDiskMountPoint(partition.Mountpoint) { continue @@ -39,12 +99,12 @@ func (d *DiskCollector) Collect() ([]protocol.DiskData, error) { continue // 跳过无法访问的分区 } - // 跳过容量为 0 的分区(可能是虚拟文件系统) + // 跳过容量为 0 的分区 if usage.Total == 0 { continue } - diskData := protocol.DiskData{ + diskDataList = append(diskDataList, protocol.DiskData{ MountPoint: partition.Mountpoint, Device: partition.Device, Fstype: partition.Fstype, @@ -52,9 +112,7 @@ func (d *DiskCollector) Collect() ([]protocol.DiskData, error) { Used: usage.Used, Free: usage.Free, UsagePercent: usage.UsedPercent, - } - - diskDataList = append(diskDataList, diskData) + }) } // 所有白名单分区均采集失败时,返回空列表表示异常 diff --git a/pkg/agent/config/config.go b/pkg/agent/config/config.go index e1a091c..a052fd9 100644 --- a/pkg/agent/config/config.go +++ b/pkg/agent/config/config.go @@ -388,23 +388,21 @@ func (c *Config) ShouldExcludeNetworkInterface(interfaceName string) bool { } // GetDiskInclude 获取磁盘包含的挂载点列表(白名单) -// 如果配置为空,返回默认的根分区匹配规则 -// Linux/macOS: ["/"] -// Windows: ["C:"] +// 返回 nil 表示未配置白名单,采集所有挂载点 func (c *Config) GetDiskInclude() []string { if len(c.Collector.DiskInclude) == 0 { - if runtime.GOOS == "windows" { - return []string{"C:"} - } - return []string{"/"} + return nil } return c.Collector.DiskInclude } // ShouldIncludeDiskMountPoint 检查挂载点是否应该被采集 -// 只有在 DiskInclude 白名单中的挂载点才会被采集 +// 未配置白名单时采集所有挂载点 func (c *Config) ShouldIncludeDiskMountPoint(mountPoint string) bool { includeMounts := c.GetDiskInclude() + if len(includeMounts) == 0 { + return true // 未配置白名单,采集所有 + } for _, mount := range includeMounts { if mountPoint == mount { return true