✨ feat(agent): 添加 token 鉴权和流程文档
* 默认监听调整为 0.0.0.0:8080,并要求查询参数 token * 支持首次 run 自动生成含随机 token 的配置文件 * 补充 HTTP 鉴权、配置校验和相关测试 * 完善代码注释,覆盖缓存、上报、服务和平台采集路径 * 新增架构与开发流程文档,补充一键构建脚本
This commit is contained in:
@@ -23,7 +23,10 @@ import (
|
||||
"mfd-monitor-agent/internal/status"
|
||||
)
|
||||
|
||||
// socketInodesFunc 是测试可替换的 Linux socket inode 到进程映射函数。
|
||||
var socketInodesFunc = socketInodes
|
||||
|
||||
// readTCPListenersFunc 是测试可替换的 Linux TCP 表解析函数。
|
||||
var readTCPListenersFunc = readTCPListeners
|
||||
|
||||
// collectSystem 从 Linux 填充主机标识、操作系统、架构与运行时长字段。
|
||||
@@ -108,6 +111,7 @@ func collectProcesses(_ context.Context, out *status.HostStatus) error {
|
||||
}
|
||||
process, err := readProcess(pid)
|
||||
if err != nil {
|
||||
// 进程可能在遍历期间退出,或因权限限制无法读取;保留其他进程并降级为 partial。
|
||||
errs = append(errs, err)
|
||||
continue
|
||||
}
|
||||
@@ -130,6 +134,7 @@ func collectSockets(_ context.Context, out *status.HostStatus) error {
|
||||
var listeners []status.TCPListenerInfo
|
||||
var errs []error
|
||||
if inodeErr != nil {
|
||||
// inode 映射失败通常意味着端口仍可见但进程归属不完整,后续继续解析 TCP 表。
|
||||
errs = append(errs, inodeErr)
|
||||
}
|
||||
for _, file := range []struct {
|
||||
@@ -285,6 +290,7 @@ func readDisks() ([]status.DiskInfo, error) {
|
||||
}
|
||||
var stat syscall.Statfs_t
|
||||
if err := syscall.Statfs(fields[1], &stat); err != nil {
|
||||
// 个别挂载点可能瞬时不可达;磁盘采集保持尽力返回其他挂载。
|
||||
continue
|
||||
}
|
||||
total := stat.Blocks * uint64(stat.Bsize)
|
||||
@@ -331,6 +337,7 @@ func readProcess(pid int) (status.ProcessInfo, error) {
|
||||
vms := parseKB(statusValues["VmSize"])
|
||||
username := ""
|
||||
if uid := firstField(statusValues["Uid"]); uid != "" {
|
||||
// 用户名解析失败不影响进程主体信息,保留空用户名表示未知。
|
||||
if u, err := user.LookupId(uid); err == nil {
|
||||
username = u.Username
|
||||
}
|
||||
@@ -339,6 +346,7 @@ func readProcess(pid int) (status.ProcessInfo, error) {
|
||||
if data, err := os.ReadFile(filepath.Join(base, "cmdline")); err == nil {
|
||||
cmdline = strings.Trim(strings.ReplaceAll(string(data), "\x00", " "), " ")
|
||||
}
|
||||
// exe 和 stat 都可能因权限或进程退出失败;这些字段按空值/零值降级。
|
||||
exe, _ := os.Readlink(filepath.Join(base, "exe"))
|
||||
statValues, _ := readProcessStat(filepath.Join(base, "stat"))
|
||||
return status.ProcessInfo{
|
||||
@@ -400,6 +408,7 @@ func socketInodes() (map[string]status.ProcessInfo, error) {
|
||||
fdDir := filepath.Join(path, "fd")
|
||||
entries, err := os.ReadDir(fdDir)
|
||||
if err != nil {
|
||||
// 无法读取 fd 目录会导致部分端口缺少 PID 映射,因此计数并向上报告 partial。
|
||||
readErrors++
|
||||
return nil
|
||||
}
|
||||
@@ -495,6 +504,7 @@ func parseAddress(raw string, family string) (string, int, error) {
|
||||
if family == "ipv6" && len(bytes) == 16 {
|
||||
reordered := make([]byte, 16)
|
||||
for i := 0; i < 16; i += 4 {
|
||||
// /proc/net/tcp6 以 32 位小端字组保存 IPv6 地址,需逐字反转为网络序。
|
||||
reordered[i], reordered[i+1], reordered[i+2], reordered[i+3] = bytes[i+3], bytes[i+2], bytes[i+1], bytes[i]
|
||||
}
|
||||
return net.IP(reordered).String(), int(port64), nil
|
||||
|
||||
Reference in New Issue
Block a user