修改客户端日志为 slog
This commit is contained in:
1 parent
a92833a5bd
commit
6c499e2464
13 files changed
+292
-168
No files matched your search
@@ -7,7 +7,7 @@ import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
@@ -29,19 +29,19 @@ type Logger interface {
|
||||
type defaultLogger struct{}
|
||||
|
||||
func (l *defaultLogger) Debug(format string, args ...interface{}) {
|
||||
log.Printf("[DEBUG] "+format, args...)
|
||||
slog.Debug(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Info(format string, args ...interface{}) {
|
||||
log.Printf("[INFO] "+format, args...)
|
||||
slog.Info(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Warn(format string, args ...interface{}) {
|
||||
log.Printf("[WARN] "+format, args...)
|
||||
slog.Warn(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (l *defaultLogger) Error(format string, args ...interface{}) {
|
||||
log.Printf("[ERROR] "+format, args...)
|
||||
slog.Error(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
var globalLogger Logger = &defaultLogger{}
|
||||
|
||||
@@ -47,6 +47,24 @@ type ServerConfig struct {
|
||||
type AgentConfig struct {
|
||||
// Agent 名称(默认使用主机名)
|
||||
Name string `yaml:"name"`
|
||||
|
||||
// 日志等级(debug, info, warn, error,默认为 info)
|
||||
LogLevel string `yaml:"log_level"`
|
||||
|
||||
// 日志文件路径(默认为空,输出到控制台)
|
||||
LogFile string `yaml:"log_file"`
|
||||
|
||||
// 日志文件最大大小(MB,默认 100MB)
|
||||
LogMaxSize int `yaml:"log_max_size"`
|
||||
|
||||
// 日志文件最大备份数(默认 3)
|
||||
LogMaxBackups int `yaml:"log_max_backups"`
|
||||
|
||||
// 日志文件最大保留天数(默认 28 天)
|
||||
LogMaxAge int `yaml:"log_max_age"`
|
||||
|
||||
// 是否压缩旧日志文件(默认 true)
|
||||
LogCompress bool `yaml:"log_compress"`
|
||||
}
|
||||
|
||||
// CollectorConfig 采集器配置
|
||||
@@ -93,7 +111,13 @@ func DefaultConfig() *Config {
|
||||
InsecureSkipVerify: false,
|
||||
},
|
||||
Agent: AgentConfig{
|
||||
Name: "",
|
||||
Name: "",
|
||||
LogLevel: "info",
|
||||
LogFile: "",
|
||||
LogMaxSize: 100,
|
||||
LogMaxBackups: 3,
|
||||
LogMaxAge: 28,
|
||||
LogCompress: true,
|
||||
},
|
||||
Collector: CollectorConfig{
|
||||
Interval: 5,
|
||||
@@ -199,6 +223,20 @@ func (c *Config) Validate() error {
|
||||
}
|
||||
}
|
||||
|
||||
// 验证日志等级
|
||||
if c.Agent.LogLevel == "" {
|
||||
c.Agent.LogLevel = "info"
|
||||
}
|
||||
validLogLevels := map[string]bool{
|
||||
"debug": true,
|
||||
"info": true,
|
||||
"warn": true,
|
||||
"error": true,
|
||||
}
|
||||
if !validLogLevels[c.Agent.LogLevel] {
|
||||
return fmt.Errorf("无效的日志等级: %s (可选值: debug, info, warn, error)", c.Agent.LogLevel)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
// LogConfig 日志配置
|
||||
type LogConfig struct {
|
||||
Level string
|
||||
File string
|
||||
MaxSize int
|
||||
MaxBackups int
|
||||
MaxAge int
|
||||
Compress bool
|
||||
}
|
||||
|
||||
// InitLogger 初始化日志系统
|
||||
func InitLogger(cfg *LogConfig) {
|
||||
var level slog.Level
|
||||
switch strings.ToLower(cfg.Level) {
|
||||
case "debug":
|
||||
level = slog.LevelDebug
|
||||
case "info":
|
||||
level = slog.LevelInfo
|
||||
case "warn":
|
||||
level = slog.LevelWarn
|
||||
case "error":
|
||||
level = slog.LevelError
|
||||
default:
|
||||
level = slog.LevelInfo
|
||||
}
|
||||
|
||||
var writer io.Writer
|
||||
|
||||
// 如果配置了日志文件,使用 lumberjack 进行日志滚动
|
||||
if cfg.File != "" {
|
||||
writer = &lumberjack.Logger{
|
||||
Filename: cfg.File,
|
||||
MaxSize: cfg.MaxSize, // MB
|
||||
MaxBackups: cfg.MaxBackups, // 保留的旧日志文件数
|
||||
MaxAge: cfg.MaxAge, // 天数
|
||||
Compress: cfg.Compress, // 是否压缩
|
||||
}
|
||||
} else {
|
||||
// 否则输出到标准输出
|
||||
writer = os.Stdout
|
||||
}
|
||||
|
||||
// 创建文本格式的 handler(更易读)
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: level,
|
||||
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
|
||||
// 格式化时间为更易读的格式
|
||||
if a.Key == slog.TimeKey {
|
||||
return slog.String(slog.TimeKey, a.Value.Time().Format("2006-01-02 15:04:05.000"))
|
||||
}
|
||||
return a
|
||||
},
|
||||
}
|
||||
handler := slog.NewTextHandler(writer, opts)
|
||||
logger := slog.New(handler)
|
||||
slog.SetDefault(logger)
|
||||
}
|
||||
+62
-62
@@ -6,7 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
@@ -106,14 +106,14 @@ func (a *Agent) Start(ctx context.Context) error {
|
||||
|
||||
// 检查是否是上下文取消
|
||||
if ctx.Err() != nil {
|
||||
log.Println("收到停止信号,探针服务退出")
|
||||
slog.Info("收到停止信号,探针服务退出")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 连接建立失败或注册失败(使用 backoff)
|
||||
if err != nil {
|
||||
retryAfter := b.Duration()
|
||||
log.Printf("⚠️ 探针运行出错: %v,将在 %v 后重试", err, retryAfter)
|
||||
slog.Warn("探针运行出错,将在后重试", "error", err, "retryAfter", retryAfter)
|
||||
|
||||
select {
|
||||
case <-time.After(retryAfter):
|
||||
@@ -124,7 +124,7 @@ func (a *Agent) Start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// 理论上不会到这里
|
||||
log.Println("连接意外结束")
|
||||
slog.Info("连接意外结束")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ func (a *Agent) Stop() {
|
||||
// 返回 error 表示需要重连,返回 nil 可能是正常关闭或上下文取消
|
||||
func (a *Agent) runOnce(ctx context.Context, onConnected func()) error {
|
||||
wsURL := a.cfg.GetWebSocketURL()
|
||||
log.Printf("🔌 正在连接到服务器: %s", wsURL)
|
||||
slog.Info("正在连接到服务器", "url", wsURL)
|
||||
|
||||
// 创建自定义的 Dialer
|
||||
var dialer = websocket.DefaultDialer
|
||||
@@ -148,7 +148,7 @@ func (a *Agent) runOnce(ctx context.Context, onConnected func()) error {
|
||||
dialer.TLSClientConfig = &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
log.Println("⚠️ 警告: 已禁用 TLS 证书验证")
|
||||
slog.Warn("警告: 已禁用 TLS 证书验证")
|
||||
}
|
||||
|
||||
// 连接到服务器
|
||||
@@ -168,7 +168,7 @@ func (a *Agent) runOnce(ctx context.Context, onConnected func()) error {
|
||||
// WriteControl 有内置锁,可以安全调用
|
||||
err := rawConn.WriteControl(websocket.PongMessage, []byte(appData), time.Now().Add(time.Second))
|
||||
if err == nil {
|
||||
//log.Println("💓 收到 Ping,已发送 Pong")
|
||||
//slog.Info("收到 Ping,已发送 Pong")
|
||||
}
|
||||
return err
|
||||
})
|
||||
@@ -178,7 +178,7 @@ func (a *Agent) runOnce(ctx context.Context, onConnected func()) error {
|
||||
return fmt.Errorf("注册失败: %w", err)
|
||||
}
|
||||
|
||||
log.Println("✅ 探针注册成功,开始监控...")
|
||||
slog.Info("探针注册成功,开始监控...")
|
||||
|
||||
// 创建采集器管理器
|
||||
collectorManager := collector.NewManager(a.cfg)
|
||||
@@ -242,11 +242,11 @@ func (a *Agent) runOnce(ctx context.Context, onConnected func()) error {
|
||||
select {
|
||||
case err := <-errChan:
|
||||
// 连接已建立,无论什么原因断开都标记为已建立状态
|
||||
log.Printf("连接断开: %v", err)
|
||||
slog.Info("连接断开", "error", err)
|
||||
returnErr = ErrConnectionEstablished
|
||||
case <-ctx.Done():
|
||||
// 收到取消信号
|
||||
log.Println("收到停止信号,准备关闭连接")
|
||||
slog.Info("收到停止信号,准备关闭连接")
|
||||
returnErr = ctx.Err()
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ func (a *Agent) runOnce(ctx context.Context, onConnected func()) error {
|
||||
// 发送 WebSocket 关闭消息
|
||||
closeMsg := websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")
|
||||
if err := conn.WriteMessage(websocket.CloseMessage, closeMsg); err != nil {
|
||||
log.Printf("⚠️ 发送关闭消息失败: %v", err)
|
||||
slog.Warn("发送关闭消息失败", "error", err)
|
||||
}
|
||||
|
||||
// 等待所有 goroutine 优雅退出
|
||||
@@ -283,7 +283,7 @@ func (a *Agent) readLoop(conn *websocket.Conn, done chan struct{}) error {
|
||||
// 解析消息
|
||||
var msg protocol.InputMessage
|
||||
if err := json.Unmarshal(message, &msg); err != nil {
|
||||
log.Printf("⚠️ 解析消息失败: %v", err)
|
||||
slog.Warn("解析消息失败", "error", err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ func (a *Agent) registerAgent(conn *safeConn) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("加载 agent ID 失败: %w", err)
|
||||
}
|
||||
log.Printf("🆔 Agent ID: %s (存储在: %s)", agentID, a.idMgr.GetPath())
|
||||
slog.Info("Agent ID", "id", agentID, "path", a.idMgr.GetPath())
|
||||
|
||||
// 获取主机信息
|
||||
hostname, _ := os.Hostname()
|
||||
@@ -369,36 +369,36 @@ func (a *Agent) registerAgent(conn *safeConn) error {
|
||||
return fmt.Errorf("解析注册响应失败: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("注册成功: AgentId=%s, Status=%s", registerResp.AgentID, registerResp.Status)
|
||||
slog.Info("注册成功", "agentId", registerResp.AgentID, "status", registerResp.Status)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Agent) handleMonitorConfig(data json.RawMessage) {
|
||||
var payload protocol.MonitorConfigPayload
|
||||
if err := json.Unmarshal(data, &payload); err != nil {
|
||||
log.Printf("⚠️ 解析监控配置失败: %v", err)
|
||||
slog.Warn("解析监控配置失败", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(payload.Items) == 0 {
|
||||
log.Println("ℹ️ 收到空的服务监控配置,跳过")
|
||||
slog.Info("收到空的服务监控配置,跳过")
|
||||
return
|
||||
}
|
||||
|
||||
conn := a.getActiveConn()
|
||||
manager := a.getCollectorManager()
|
||||
if conn == nil || manager == nil {
|
||||
log.Println("⚠️ 当前连接未就绪,无法执行服务监控任务")
|
||||
slog.Warn("当前连接未就绪,无法执行服务监控任务")
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("📥 收到服务监控配置,总计 %d 个监控项,立即执行检测", len(payload.Items))
|
||||
slog.Info("收到服务监控配置,立即执行检测", "count", len(payload.Items))
|
||||
|
||||
// 立即执行一次监控检测
|
||||
if err := manager.CollectAndSendMonitor(conn, payload.Items); err != nil {
|
||||
log.Printf("⚠️ 监控检测失败: %v", err)
|
||||
slog.Warn("监控检测失败", "error", err)
|
||||
} else {
|
||||
log.Printf("✅ 服务监控检测完成,已上报 %d 个监控项结果", len(payload.Items))
|
||||
slog.Info("服务监控检测完成,已上报监控项结果", "count", len(payload.Items))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ func (a *Agent) heartbeatLoop(ctx context.Context, conn *safeConn, done chan str
|
||||
}); err != nil {
|
||||
return fmt.Errorf("发送心跳失败: %w", err)
|
||||
}
|
||||
//log.Println("💓 心跳已发送")
|
||||
//slog.Info("心跳已发送")
|
||||
case <-done:
|
||||
return nil
|
||||
case <-ctx.Done():
|
||||
@@ -453,7 +453,7 @@ func (a *Agent) getCollectorManager() *collector.Manager {
|
||||
func (a *Agent) metricsLoop(ctx context.Context, conn *safeConn, manager *collector.Manager, done chan struct{}) error {
|
||||
// 立即采集一次动态数据
|
||||
if err := a.collectAndSendAllMetrics(conn, manager); err != nil {
|
||||
log.Printf("⚠️ 初始数据采集失败: %v", err)
|
||||
slog.Warn("初始数据采集失败", "error", err)
|
||||
}
|
||||
|
||||
// 定时采集动态指标
|
||||
@@ -481,54 +481,54 @@ func (a *Agent) collectAndSendAllMetrics(conn *safeConn, manager *collector.Mana
|
||||
|
||||
// CPU 动态指标
|
||||
if err := manager.CollectAndSendCPU(conn); err != nil {
|
||||
log.Printf("⚠️ 发送CPU指标失败: %v", err)
|
||||
slog.Warn("发送CPU指标失败", "error", err)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
// 内存动态指标
|
||||
if err := manager.CollectAndSendMemory(conn); err != nil {
|
||||
log.Printf("⚠️ 发送内存指标失败: %v", err)
|
||||
slog.Warn("发送内存指标失败", "error", err)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
// 磁盘指标
|
||||
if err := manager.CollectAndSendDisk(conn); err != nil {
|
||||
log.Printf("⚠️ 发送磁盘指标失败: %v", err)
|
||||
slog.Warn("发送磁盘指标失败", "error", err)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
// 磁盘 IO 指标
|
||||
if err := manager.CollectAndSendDiskIO(conn); err != nil {
|
||||
log.Printf("⚠️ 发送磁盘IO指标失败: %v", err)
|
||||
slog.Warn("发送磁盘IO指标失败", "error", err)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
// 网络指标
|
||||
if err := manager.CollectAndSendNetwork(conn); err != nil {
|
||||
log.Printf("⚠️ 发送网络指标失败: %v", err)
|
||||
slog.Warn("发送网络指标失败", "error", err)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
// 网络连接统计
|
||||
if err := manager.CollectAndSendNetworkConnection(conn); err != nil {
|
||||
log.Printf("⚠️ 发送网络连接统计失败: %v", err)
|
||||
slog.Warn("发送网络连接统计失败", "error", err)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
// 主机信息
|
||||
if err := manager.CollectAndSendHost(conn); err != nil {
|
||||
log.Printf("⚠️ 发送主机信息失败: %v", err)
|
||||
slog.Warn("发送主机信息失败", "error", err)
|
||||
hasError = true
|
||||
}
|
||||
|
||||
// GPU 信息(可选)
|
||||
if err := manager.CollectAndSendGPU(conn); err != nil {
|
||||
log.Printf("ℹ️ 发送GPU信息失败: %v", err)
|
||||
slog.Info("发送GPU信息失败", "error", err)
|
||||
}
|
||||
|
||||
// 温度信息(可选)
|
||||
if err := manager.CollectAndSendTemperature(conn); err != nil {
|
||||
log.Printf("ℹ️ 发送温度信息失败: %v", err)
|
||||
slog.Info("发送温度信息失败", "error", err)
|
||||
}
|
||||
|
||||
if hasError {
|
||||
@@ -542,11 +542,11 @@ func (a *Agent) collectAndSendAllMetrics(conn *safeConn, manager *collector.Mana
|
||||
func (a *Agent) handleCommand(data json.RawMessage) {
|
||||
var cmdReq protocol.CommandRequest
|
||||
if err := json.Unmarshal(data, &cmdReq); err != nil {
|
||||
log.Printf("⚠️ 解析指令失败: %v", err)
|
||||
slog.Warn("解析指令失败", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("📥 收到指令: %s (ID: %s)", cmdReq.Type, cmdReq.ID)
|
||||
slog.Info("收到指令", "type", cmdReq.Type, "id", cmdReq.ID)
|
||||
|
||||
conn := a.getActiveConn()
|
||||
// 发送运行中状态
|
||||
@@ -556,7 +556,7 @@ func (a *Agent) handleCommand(data json.RawMessage) {
|
||||
case "vps_audit":
|
||||
a.handleVPSAudit(conn, cmdReq.ID)
|
||||
default:
|
||||
log.Printf("⚠️ 未知指令类型: %s", cmdReq.Type)
|
||||
slog.Warn("未知指令类型", "type", cmdReq.Type)
|
||||
a.sendCommandResponse(conn, cmdReq.ID, cmdReq.Type, "error", "未知指令类型", "")
|
||||
}
|
||||
}
|
||||
@@ -566,7 +566,7 @@ func (a *Agent) handleVPSAudit(conn *safeConn, cmdID string) {
|
||||
// 导入 audit 包
|
||||
result, err := a.runVPSAudit()
|
||||
if err != nil {
|
||||
log.Printf("❌ VPS安全审计失败: %v", err)
|
||||
slog.Error("VPS安全审计失败", "error", err)
|
||||
a.sendCommandResponse(conn, cmdID, "vps_audit", "error", err.Error(), "")
|
||||
return
|
||||
}
|
||||
@@ -574,12 +574,12 @@ func (a *Agent) handleVPSAudit(conn *safeConn, cmdID string) {
|
||||
// 将结果序列化为JSON
|
||||
resultJSON, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
log.Printf("❌ 序列化审计结果失败: %v", err)
|
||||
slog.Error("序列化审计结果失败", "error", err)
|
||||
a.sendCommandResponse(conn, cmdID, "vps_audit", "error", "序列化结果失败", "")
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("✅ VPS安全审计完成")
|
||||
slog.Info("VPS安全审计完成")
|
||||
a.sendCommandResponse(conn, cmdID, "vps_audit", "success", "", string(resultJSON))
|
||||
}
|
||||
|
||||
@@ -602,7 +602,7 @@ func (a *Agent) sendCommandResponse(conn *safeConn, cmdID, cmdType, status, errM
|
||||
Type: protocol.MessageTypeCommandResp,
|
||||
Data: resp,
|
||||
}); err != nil {
|
||||
log.Printf("⚠️ 发送指令响应失败: %v", err)
|
||||
slog.Warn("发送指令响应失败", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,22 +615,22 @@ func GetVersion() string {
|
||||
func (a *Agent) handleTamperProtect(data json.RawMessage) {
|
||||
var tamperProtectConfig protocol.TamperProtectConfig
|
||||
if err := json.Unmarshal(data, &tamperProtectConfig); err != nil {
|
||||
log.Printf("⚠️ 解析防篡改保护配置失败: %v", err)
|
||||
slog.Warn("解析防篡改保护配置失败", "error", err)
|
||||
a.sendTamperProtectResponse(false, "解析配置失败", nil, nil, nil, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("📥 收到防篡改保护增量配置: Added=%v, Removed=%v", tamperProtectConfig.Added, tamperProtectConfig.Removed)
|
||||
slog.Info("收到防篡改保护增量配置", "added", tamperProtectConfig.Added, "removed", tamperProtectConfig.Removed)
|
||||
|
||||
conn := a.getActiveConn()
|
||||
if conn == nil {
|
||||
log.Println("⚠️ 当前连接未就绪,无法执行防篡改保护")
|
||||
slog.Warn("当前连接未就绪,无法执行防篡改保护")
|
||||
return
|
||||
}
|
||||
|
||||
// 如果没有新增也没有移除,不需要做任何操作
|
||||
if len(tamperProtectConfig.Added) == 0 && len(tamperProtectConfig.Removed) == 0 {
|
||||
log.Println("ℹ️ 配置无变化,跳过更新")
|
||||
slog.Info("配置无变化,跳过更新")
|
||||
a.sendTamperProtectResponse(true, "配置无变化", a.tamperProtector.GetProtectedPaths(), []string{}, []string{}, "")
|
||||
return
|
||||
}
|
||||
@@ -640,7 +640,7 @@ func (a *Agent) handleTamperProtect(data json.RawMessage) {
|
||||
// 应用增量更新
|
||||
result, err := a.tamperProtector.ApplyIncrementalUpdate(ctx, tamperProtectConfig.Added, tamperProtectConfig.Removed)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 应用增量更新失败: %v", err)
|
||||
slog.Warn("应用增量更新失败", "error", err)
|
||||
// 即使有错误也返回部分成功的结果
|
||||
if result != nil {
|
||||
a.sendTamperProtectResponse(false, "部分更新失败", result.Current, result.Added, result.Removed, err.Error())
|
||||
@@ -653,7 +653,7 @@ func (a *Agent) handleTamperProtect(data json.RawMessage) {
|
||||
// 成功更新
|
||||
message := fmt.Sprintf("防篡改保护已更新: 新增 %d 个, 移除 %d 个, 当前保护 %d 个目录",
|
||||
len(result.Added), len(result.Removed), len(result.Current))
|
||||
log.Printf("✅ %s", message)
|
||||
slog.Info(message)
|
||||
a.sendTamperProtectResponse(true, message, result.Current, result.Added, result.Removed, "")
|
||||
}
|
||||
|
||||
@@ -677,7 +677,7 @@ func (a *Agent) sendTamperProtectResponse(success bool, message string, paths []
|
||||
Type: protocol.MessageTypeTamperProtect,
|
||||
Data: resp,
|
||||
}); err != nil {
|
||||
log.Printf("⚠️ 发送防篡改保护响应失败: %v", err)
|
||||
slog.Warn("发送防篡改保护响应失败", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,9 +704,9 @@ func (a *Agent) tamperEventLoop(ctx context.Context, conn *safeConn, done chan s
|
||||
Type: protocol.MessageTypeTamperEvent,
|
||||
Data: eventData,
|
||||
}); err != nil {
|
||||
log.Printf("⚠️ 发送防篡改事件失败: %v", err)
|
||||
slog.Warn("发送防篡改事件失败", "error", err)
|
||||
} else {
|
||||
log.Printf("📤 已上报防篡改事件: %s - %s", event.Path, event.Operation)
|
||||
slog.Info("已上报防篡改事件", "path", event.Path, "operation", event.Operation)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -735,13 +735,13 @@ func (a *Agent) tamperAlertLoop(ctx context.Context, conn *safeConn, done chan s
|
||||
Type: protocol.MessageTypeTamperAlert,
|
||||
Data: alertData,
|
||||
}); err != nil {
|
||||
log.Printf("⚠️ 发送属性篡改告警失败: %v", err)
|
||||
slog.Warn("发送属性篡改告警失败", "error", err)
|
||||
} else {
|
||||
status := "未恢复"
|
||||
if alert.Restored {
|
||||
status = "已恢复"
|
||||
}
|
||||
log.Printf("📤 已上报属性篡改告警: %s - %s", alert.Path, status)
|
||||
slog.Info("已上报属性篡改告警", "path", alert.Path, "status", status)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -751,29 +751,29 @@ func (a *Agent) tamperAlertLoop(ctx context.Context, conn *safeConn, done chan s
|
||||
func (a *Agent) handleDDNSConfig(data json.RawMessage) {
|
||||
var ddnsConfig protocol.DDNSConfigData
|
||||
if err := json.Unmarshal(data, &ddnsConfig); err != nil {
|
||||
log.Printf("⚠️ 解析 DDNS 配置失败: %v", err)
|
||||
slog.Warn("解析 DDNS 配置失败", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
if !ddnsConfig.Enabled {
|
||||
log.Println("ℹ️ DDNS 已禁用,跳过 IP 检查")
|
||||
slog.Info("DDNS 已禁用,跳过 IP 检查")
|
||||
return
|
||||
}
|
||||
|
||||
conn := a.getActiveConn()
|
||||
manager := a.getCollectorManager()
|
||||
if conn == nil || manager == nil {
|
||||
log.Println("⚠️ 当前连接未就绪,无法执行 DDNS IP 检查")
|
||||
slog.Warn("当前连接未就绪,无法执行 DDNS IP 检查")
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("📥 收到 DDNS 配置检查请求,开始采集 IP 地址")
|
||||
slog.Info("收到 DDNS 配置检查请求,开始采集 IP 地址")
|
||||
|
||||
// 采集 IP 地址并上报
|
||||
if err := a.collectAndSendDDNSIP(conn, manager, &ddnsConfig); err != nil {
|
||||
log.Printf("⚠️ DDNS IP 采集失败: %v", err)
|
||||
slog.Warn("DDNS IP 采集失败", "error", err)
|
||||
} else {
|
||||
log.Println("✅ DDNS IP 地址已上报")
|
||||
slog.Info("DDNS IP 地址已上报")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -785,10 +785,10 @@ func (a *Agent) collectAndSendDDNSIP(conn *safeConn, manager *collector.Manager,
|
||||
if config.EnableIPv4 {
|
||||
ipv4, err := a.getIPAddress(manager, config.IPv4GetMethod, config.IPv4GetValue, false)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 获取 IPv4 失败: %v", err)
|
||||
slog.Warn("获取 IPv4 失败", "error", err)
|
||||
} else {
|
||||
ipReport.IPv4 = ipv4
|
||||
log.Printf("✅ 获取 IPv4: %s", ipv4)
|
||||
slog.Info("获取 IPv4", "ip", ipv4)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -796,10 +796,10 @@ func (a *Agent) collectAndSendDDNSIP(conn *safeConn, manager *collector.Manager,
|
||||
if config.EnableIPv6 {
|
||||
ipv6, err := a.getIPAddress(manager, config.IPv6GetMethod, config.IPv6GetValue, true)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 获取 IPv6 失败: %v", err)
|
||||
slog.Warn("获取 IPv6 失败", "error", err)
|
||||
} else {
|
||||
ipReport.IPv6 = ipv6
|
||||
log.Printf("✅ 获取 IPv6: %s", ipv6)
|
||||
slog.Info("获取 IPv6", "ip", ipv6)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -834,7 +834,7 @@ func (a *Agent) getIPAddress(manager *collector.Manager, method, value string, i
|
||||
|
||||
// handleUninstall 处理服务端发送的卸载指令
|
||||
func (a *Agent) handleUninstall() {
|
||||
log.Println("📥 收到服务端卸载指令,开始执行卸载...")
|
||||
slog.Info("收到服务端卸载指令,开始执行卸载...")
|
||||
|
||||
// 获取配置文件路径
|
||||
cfgPath := a.cfg.Path
|
||||
@@ -844,11 +844,11 @@ func (a *Agent) handleUninstall() {
|
||||
|
||||
// 执行卸载操作
|
||||
if err := UninstallAgent(cfgPath); err != nil {
|
||||
log.Printf("❌ 卸载失败: %v", err)
|
||||
slog.Error("卸载失败", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("✅ 探针卸载成功,即将退出...")
|
||||
slog.Info("探针卸载成功,即将退出...")
|
||||
|
||||
// 卸载成功后,触发停止信号
|
||||
if a.cancel != nil {
|
||||
|
||||
@@ -3,11 +3,12 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/dushixiang/pika/pkg/agent"
|
||||
"github.com/dushixiang/pika/pkg/agent/config"
|
||||
"github.com/dushixiang/pika/pkg/agent/id"
|
||||
"github.com/dushixiang/pika/pkg/agent/sysutil"
|
||||
@@ -26,9 +27,8 @@ type program struct {
|
||||
// configureICMP 配置 ICMP 权限(抽取通用逻辑)
|
||||
func configureICMP() {
|
||||
if err := sysutil.ConfigureICMPPermissions(); err != nil {
|
||||
log.Printf("⚠️ 配置 ICMP 权限失败: %v", err)
|
||||
log.Println(" 提示: ICMP 监控可能需要 root 权限运行,或手动执行:")
|
||||
log.Println(" sudo sysctl -w net.ipv4.ping_group_range=\"0 2147483647\"")
|
||||
slog.Warn("配置 ICMP 权限失败", "error", err)
|
||||
slog.Info("提示: ICMP 监控可能需要 root 权限运行,或手动执行: sudo sysctl -w net.ipv4.ping_group_range=\"0 2147483647\"")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ func startAgent(ctx context.Context, cfg *config.Config) *Agent {
|
||||
if cfg.AutoUpdate.Enabled {
|
||||
upd, err := updater.New(cfg, GetVersion())
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 创建更新器失败: %v", err)
|
||||
slog.Warn("创建更新器失败", "error", err)
|
||||
} else {
|
||||
go upd.Start(ctx)
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func startAgent(ctx context.Context, cfg *config.Config) *Agent {
|
||||
// 在后台启动 Agent
|
||||
go func() {
|
||||
if err := agent.Start(ctx); err != nil {
|
||||
log.Printf("⚠️ 探针运行出错: %v", err)
|
||||
slog.Warn("探针运行出错", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -59,7 +59,17 @@ func startAgent(ctx context.Context, cfg *config.Config) *Agent {
|
||||
|
||||
// Start 启动服务
|
||||
func (p *program) Start(s service.Service) error {
|
||||
log.Println("✅ Pika Agent 服务启动中...")
|
||||
// 初始化日志系统
|
||||
agent.InitLogger(&agent.LogConfig{
|
||||
Level: p.cfg.Agent.LogLevel,
|
||||
File: p.cfg.Agent.LogFile,
|
||||
MaxSize: p.cfg.Agent.LogMaxSize,
|
||||
MaxBackups: p.cfg.Agent.LogMaxBackups,
|
||||
MaxAge: p.cfg.Agent.LogMaxAge,
|
||||
Compress: p.cfg.Agent.LogCompress,
|
||||
})
|
||||
|
||||
slog.Info("Pika Agent 服务启动中...")
|
||||
|
||||
// 初始化系统配置(Linux ICMP 权限等)
|
||||
configureICMP()
|
||||
@@ -75,7 +85,7 @@ func (p *program) Start(s service.Service) error {
|
||||
|
||||
// Stop 停止服务
|
||||
func (p *program) Stop(s service.Service) error {
|
||||
log.Println("📴 Pika Agent 服务停止中...")
|
||||
slog.Info("Pika Agent 服务停止中...")
|
||||
|
||||
if p.cancel != nil {
|
||||
p.cancel()
|
||||
@@ -85,7 +95,7 @@ func (p *program) Stop(s service.Service) error {
|
||||
p.agent.Stop()
|
||||
}
|
||||
|
||||
log.Println("✅ Pika Agent 服务已停止")
|
||||
slog.Info("Pika Agent 服务已停止")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -206,10 +216,20 @@ func (m *ServiceManager) Run() error {
|
||||
}
|
||||
|
||||
// 交互模式(前台运行)
|
||||
log.Printf("✅ 配置加载成功")
|
||||
log.Printf(" 服务器地址: %s", m.cfg.Server.Endpoint)
|
||||
log.Printf(" 采集间隔: %v", m.cfg.GetCollectorInterval())
|
||||
log.Printf(" 心跳间隔: %v", m.cfg.GetHeartbeatInterval())
|
||||
// 初始化日志系统
|
||||
agent.InitLogger(&agent.LogConfig{
|
||||
Level: m.cfg.Agent.LogLevel,
|
||||
File: m.cfg.Agent.LogFile,
|
||||
MaxSize: m.cfg.Agent.LogMaxSize,
|
||||
MaxBackups: m.cfg.Agent.LogMaxBackups,
|
||||
MaxAge: m.cfg.Agent.LogMaxAge,
|
||||
Compress: m.cfg.Agent.LogCompress,
|
||||
})
|
||||
|
||||
slog.Info("配置加载成功",
|
||||
"server_endpoint", m.cfg.Server.Endpoint,
|
||||
"collector_interval", m.cfg.GetCollectorInterval(),
|
||||
"heartbeat_interval", m.cfg.GetHeartbeatInterval())
|
||||
|
||||
// 初始化系统配置(Linux ICMP 权限等)
|
||||
configureICMP()
|
||||
@@ -227,12 +247,12 @@ func (m *ServiceManager) Run() error {
|
||||
|
||||
// 等待中断信号
|
||||
<-interrupt
|
||||
log.Println("📴 收到中断信号,正在关闭...")
|
||||
slog.Info("收到中断信号,正在关闭...")
|
||||
cancel()
|
||||
|
||||
// 等待 Agent 停止
|
||||
agent.Stop()
|
||||
log.Println("✅ 探针已停止")
|
||||
slog.Info("探针已停止")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -254,7 +274,7 @@ func UninstallAgent(cfgPath string) error {
|
||||
// 检查服务状态,如果在运行则停止
|
||||
status, err := mgr.Status()
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 获取服务状态失败: %v", err)
|
||||
slog.Warn("获取服务状态失败", "error", err)
|
||||
} else if status != "已停止 (Stopped)" {
|
||||
if err := mgr.Stop(); err != nil {
|
||||
return fmt.Errorf("停止服务失败: %w", err)
|
||||
@@ -268,13 +288,13 @@ func UninstallAgent(cfgPath string) error {
|
||||
|
||||
// 删除配置文件
|
||||
if err := os.Remove(cfgPath); err != nil {
|
||||
log.Printf("⚠️ 删除配置文件失败: %v", err)
|
||||
slog.Warn("删除配置文件失败", "error", err)
|
||||
}
|
||||
|
||||
// 删除探针 ID 文件
|
||||
idPath := id.GetIDFilePath()
|
||||
if err := os.Remove(idPath); err != nil {
|
||||
log.Printf("⚠️ 删除探针 ID 文件失败: %v", err)
|
||||
slog.Warn("删除探针 ID 文件失败", "error", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -2,7 +2,7 @@ package sysutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -27,19 +27,18 @@ func doConfigureICMPPermissions() error {
|
||||
|
||||
// 2. 检查是否已经满足要求 (范围包含 0 到 2147483647)
|
||||
if currentMin <= 0 && currentMax >= 2147483647 {
|
||||
log.Printf("✅ ICMP 权限已配置: net.ipv4.ping_group_range=%d %d", currentMin, currentMax)
|
||||
slog.Info("ICMP 权限已配置", "min", currentMin, "max", currentMax)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 3. 需要配置,写入新值
|
||||
log.Printf("🔧 当前 ICMP 配置: net.ipv4.ping_group_range=%d %d (不满足要求)", currentMin, currentMax)
|
||||
log.Println(" 正在配置为: 0 2147483647")
|
||||
slog.Info("当前 ICMP 配置不满足要求,正在配置", "current_min", currentMin, "current_max", currentMax, "target", "0 2147483647")
|
||||
|
||||
if err := writePingGroupRange(sysctlPath, 0, 2147483647); err != nil {
|
||||
return fmt.Errorf("配置 ICMP 权限失败: %w", err)
|
||||
}
|
||||
|
||||
log.Println("✅ ICMP 权限配置成功: net.ipv4.ping_group_range=0 2147483647")
|
||||
slog.Info("ICMP 权限配置成功", "range", "0 2147483647")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package tamper
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
@@ -72,7 +72,7 @@ func (p *Protector) ApplyIncrementalUpdate(ctx context.Context, toAdd, toRemove
|
||||
|
||||
// 如果没有变化,直接返回
|
||||
if len(toAdd) == 0 && len(toRemove) == 0 {
|
||||
log.Println("ℹ️ 防篡改保护目录列表无变化")
|
||||
slog.Info("防篡改保护目录列表无变化")
|
||||
return &UpdateResult{
|
||||
Added: []string{},
|
||||
Removed: []string{},
|
||||
@@ -91,15 +91,15 @@ func (p *Protector) ApplyIncrementalUpdate(ctx context.Context, toAdd, toRemove
|
||||
var removeFailed []string
|
||||
for _, path := range toRemove {
|
||||
if !p.paths[path] {
|
||||
log.Printf("ℹ️ 目录 %s 未被保护,跳过移除", path)
|
||||
slog.Info("目录未被保护,跳过移除", "path", path)
|
||||
continue
|
||||
}
|
||||
if err := p.removePath(path); err != nil {
|
||||
log.Printf("⚠️ 移除目录 %s 保护失败: %v", path, err)
|
||||
slog.Warn("移除目录保护失败", "path", path, "error", err)
|
||||
removeFailed = append(removeFailed, path)
|
||||
} else {
|
||||
delete(p.paths, path)
|
||||
log.Printf("✅ 已取消保护目录: %s", path)
|
||||
slog.Info("已取消保护目录", "path", path)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,15 +107,15 @@ func (p *Protector) ApplyIncrementalUpdate(ctx context.Context, toAdd, toRemove
|
||||
var addFailed []string
|
||||
for _, path := range toAdd {
|
||||
if p.paths[path] {
|
||||
log.Printf("ℹ️ 目录 %s 已被保护,跳过新增", path)
|
||||
slog.Info("目录已被保护,跳过新增", "path", path)
|
||||
continue
|
||||
}
|
||||
if err := p.addPath(path); err != nil {
|
||||
log.Printf("⚠️ 添加目录 %s 保护失败: %v", path, err)
|
||||
slog.Warn("添加目录保护失败", "path", path, "error", err)
|
||||
addFailed = append(addFailed, path)
|
||||
} else {
|
||||
p.paths[path] = true
|
||||
log.Printf("✅ 已保护目录: %s", path)
|
||||
slog.Info("已保护目录", "path", path)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,8 +131,10 @@ func (p *Protector) ApplyIncrementalUpdate(ctx context.Context, toAdd, toRemove
|
||||
return result, fmt.Errorf("部分操作失败: 添加失败 %d 个, 移除失败 %d 个", len(addFailed), len(removeFailed))
|
||||
}
|
||||
|
||||
log.Printf("✅ 防篡改保护已更新: 新增 %d 个目录, 移除 %d 个目录, 当前保护 %d 个目录",
|
||||
len(result.Added), len(result.Removed), len(result.Current))
|
||||
slog.Info("防篡改保护已更新",
|
||||
"新增", len(result.Added),
|
||||
"移除", len(result.Removed),
|
||||
"当前保护", len(result.Current))
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@@ -173,7 +175,7 @@ func (p *Protector) UpdatePaths(ctx context.Context, newPaths []string) (*Update
|
||||
|
||||
// 如果没有变化,直接返回
|
||||
if len(toAdd) == 0 && len(toRemove) == 0 {
|
||||
log.Println("ℹ️ 防篡改保护目录列表无变化")
|
||||
slog.Info("防篡改保护目录列表无变化")
|
||||
return &UpdateResult{
|
||||
Added: []string{},
|
||||
Removed: []string{},
|
||||
@@ -190,11 +192,11 @@ func (p *Protector) UpdatePaths(ctx context.Context, newPaths []string) (*Update
|
||||
var removeFailed []string
|
||||
for _, path := range toRemove {
|
||||
if err := p.removePath(path); err != nil {
|
||||
log.Printf("⚠️ 移除目录 %s 保护失败: %v", path, err)
|
||||
slog.Warn("移除目录保护失败", "path", path, "error", err)
|
||||
removeFailed = append(removeFailed, path)
|
||||
} else {
|
||||
delete(p.paths, path)
|
||||
log.Printf("✅ 已取消保护目录: %s", path)
|
||||
slog.Info("已取消保护目录", "path", path)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,11 +204,11 @@ func (p *Protector) UpdatePaths(ctx context.Context, newPaths []string) (*Update
|
||||
var addFailed []string
|
||||
for _, path := range toAdd {
|
||||
if err := p.addPath(path); err != nil {
|
||||
log.Printf("⚠️ 添加目录 %s 保护失败: %v", path, err)
|
||||
slog.Warn("添加目录保护失败", "path", path, "error", err)
|
||||
addFailed = append(addFailed, path)
|
||||
} else {
|
||||
p.paths[path] = true
|
||||
log.Printf("✅ 已保护目录: %s", path)
|
||||
slog.Info("已保护目录", "path", path)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,8 +224,10 @@ func (p *Protector) UpdatePaths(ctx context.Context, newPaths []string) (*Update
|
||||
return result, fmt.Errorf("部分操作失败: 添加失败 %d 个, 移除失败 %d 个", len(addFailed), len(removeFailed))
|
||||
}
|
||||
|
||||
log.Printf("✅ 防篡改保护已更新: 新增 %d 个目录, 移除 %d 个目录, 当前保护 %d 个目录",
|
||||
len(result.Added), len(result.Removed), len(result.Current))
|
||||
slog.Info("防篡改保护已更新",
|
||||
"新增", len(result.Added),
|
||||
"移除", len(result.Removed),
|
||||
"当前保护", len(result.Current))
|
||||
|
||||
return result, nil
|
||||
}
|
||||
@@ -234,7 +238,7 @@ func (p *Protector) StopAll() error {
|
||||
defer p.mu.Unlock()
|
||||
|
||||
if len(p.paths) == 0 {
|
||||
log.Println("ℹ️ 没有正在保护的目录")
|
||||
slog.Info("没有正在保护的目录")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -255,7 +259,7 @@ func (p *Protector) StopAll() error {
|
||||
// 关闭监控器
|
||||
if p.watcher != nil {
|
||||
if err := p.watcher.Close(); err != nil {
|
||||
log.Printf("⚠️ 关闭文件监控器失败: %v", err)
|
||||
slog.Warn("关闭文件监控器失败", "error", err)
|
||||
lastErr = err
|
||||
}
|
||||
p.watcher = nil
|
||||
@@ -265,17 +269,17 @@ func (p *Protector) StopAll() error {
|
||||
// 移除所有目录的不可变属性
|
||||
for path := range p.paths {
|
||||
if err := p.setImmutable(path, false); err != nil {
|
||||
log.Printf("⚠️ 移除目录 %s 不可变属性失败: %v", path, err)
|
||||
slog.Warn("移除目录不可变属性失败", "path", path, "error", err)
|
||||
lastErr = err
|
||||
} else {
|
||||
log.Printf("✅ 已取消保护目录: %s", path)
|
||||
slog.Info("已取消保护目录", "path", path)
|
||||
}
|
||||
}
|
||||
|
||||
// 清空路径列表
|
||||
p.paths = make(map[string]bool)
|
||||
|
||||
log.Println("✅ 已停止所有防篡改保护")
|
||||
slog.Info("已停止所有防篡改保护")
|
||||
return lastErr
|
||||
}
|
||||
|
||||
@@ -333,7 +337,7 @@ func (p *Protector) initWatcher(ctx context.Context) error {
|
||||
p.checkTicker = time.NewTicker(5 * time.Second)
|
||||
go p.periodicAttributeCheck()
|
||||
|
||||
log.Println("✅ 文件监控器已启动")
|
||||
slog.Info("文件监控器已启动")
|
||||
})
|
||||
return err
|
||||
}
|
||||
@@ -362,7 +366,7 @@ func (p *Protector) removePath(path string) error {
|
||||
// 从监控中移除
|
||||
if p.watcher != nil {
|
||||
if err := p.watcher.Remove(path); err != nil {
|
||||
log.Printf("⚠️ 从监控中移除目录失败: %v", err)
|
||||
slog.Warn("从监控中移除目录失败", "error", err)
|
||||
// 继续执行,不返回错误
|
||||
}
|
||||
}
|
||||
@@ -390,7 +394,7 @@ func (p *Protector) watchLoop() {
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
log.Printf("⚠️ 文件监控错误: %v", err)
|
||||
slog.Warn("文件监控错误", "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -431,9 +435,9 @@ func (p *Protector) handleEvent(event fsnotify.Event) {
|
||||
// 发送事件(非阻塞)
|
||||
select {
|
||||
case p.eventCh <- tamperEvent:
|
||||
log.Printf("🚨 检测到文件变动: %s - %s (%s)", event.Name, operation, details)
|
||||
slog.Warn("检测到文件变动", "path", event.Name, "operation", operation, "details", details)
|
||||
default:
|
||||
log.Printf("⚠️ 事件队列已满,丢弃事件: %s", event.Name)
|
||||
slog.Warn("事件队列已满,丢弃事件", "path", event.Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,20 +472,20 @@ func (p *Protector) checkAndRestoreImmutable(path string) {
|
||||
// 检查不可变属性
|
||||
hasImmutable, err := p.checkImmutable(path)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 检查目录 %s 属性失败: %v", path, err)
|
||||
slog.Warn("检查目录属性失败", "path", path, "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 如果不可变属性被移除
|
||||
if !hasImmutable {
|
||||
log.Printf("🚨 检测到属性篡改: %s 的不可变属性被移除", path)
|
||||
slog.Warn("检测到属性篡改", "path", path, "details", "不可变属性被移除")
|
||||
|
||||
// 尝试恢复属性
|
||||
restored := false
|
||||
if err := p.setImmutable(path, true); err != nil {
|
||||
log.Printf("❌ 恢复目录 %s 不可变属性失败: %v", path, err)
|
||||
slog.Error("恢复目录不可变属性失败", "path", path, "error", err)
|
||||
} else {
|
||||
log.Printf("✅ 已自动恢复目录 %s 的不可变属性", path)
|
||||
slog.Info("已自动恢复目录的不可变属性", "path", path)
|
||||
restored = true
|
||||
}
|
||||
|
||||
@@ -495,9 +499,9 @@ func (p *Protector) checkAndRestoreImmutable(path string) {
|
||||
|
||||
select {
|
||||
case p.alertCh <- alert:
|
||||
log.Printf("📤 已发送属性篡改告警: %s", path)
|
||||
slog.Info("已发送属性篡改告警", "path", path)
|
||||
default:
|
||||
log.Printf("⚠️ 告警队列已满,丢弃告警: %s", path)
|
||||
slog.Warn("告警队列已满,丢弃告警", "path", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
@@ -57,11 +57,11 @@ func New(cfg *config.Config, currentVer string) (*Updater, error) {
|
||||
// Start 启动自动更新检查
|
||||
func (u *Updater) Start(ctx context.Context) {
|
||||
if !u.cfg.AutoUpdate.Enabled {
|
||||
log.Println("自动更新已禁用")
|
||||
slog.Info("自动更新已禁用")
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("自动更新已启用,检查间隔: %v", u.cfg.GetUpdateCheckInterval())
|
||||
slog.Info("自动更新已启用", "check_interval", u.cfg.GetUpdateCheckInterval())
|
||||
|
||||
// 立即检查一次
|
||||
u.CheckAndUpdate()
|
||||
@@ -75,7 +75,7 @@ func (u *Updater) Start(ctx context.Context) {
|
||||
case <-ticker.C:
|
||||
u.CheckAndUpdate()
|
||||
case <-ctx.Done():
|
||||
log.Println("停止自动更新检查")
|
||||
slog.Info("停止自动更新检查")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -83,30 +83,30 @@ func (u *Updater) Start(ctx context.Context) {
|
||||
|
||||
// CheckAndUpdate 检查并更新
|
||||
func (u *Updater) CheckAndUpdate() {
|
||||
log.Println("🔍 检查更新...")
|
||||
slog.Debug("检查更新...")
|
||||
|
||||
// 获取最新版本信息
|
||||
versionInfo, err := u.fetchLatestVersion()
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 获取版本信息失败: %v", err)
|
||||
slog.Warn("获取版本信息失败", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 比较版本
|
||||
if versionInfo.Version == u.currentVer {
|
||||
log.Printf("✅ 当前已是最新版本: %s", u.currentVer)
|
||||
slog.Debug("当前已是最新版本", "version", u.currentVer)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("🆕 发现新版本: %s (当前版本: %s)", versionInfo.Version, u.currentVer)
|
||||
slog.Info("发现新版本", "new_version", versionInfo.Version, "current_version", u.currentVer)
|
||||
|
||||
// 下载新版本
|
||||
if err := u.downloadAndUpdate(versionInfo); err != nil {
|
||||
log.Printf("❌ 更新失败: %v", err)
|
||||
slog.Error("更新失败", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("✅ 更新成功,将在下次重启时生效")
|
||||
slog.Info("更新成功,将在下次重启时生效")
|
||||
}
|
||||
|
||||
// fetchLatestVersion 获取最新版本信息
|
||||
@@ -137,7 +137,7 @@ func (u *Updater) checkUpdateWithClient(latestVersionURL string) (*VersionInfo,
|
||||
|
||||
// downloadAndUpdate 下载并更新
|
||||
func (u *Updater) downloadAndUpdate(versionInfo *VersionInfo) error {
|
||||
log.Printf("📥 下载新版本: %s", versionInfo.Version)
|
||||
slog.Info("下载新版本", "version", versionInfo.Version)
|
||||
|
||||
downloadURL := u.cfg.GetDownloadURL()
|
||||
|
||||
@@ -157,7 +157,7 @@ func (u *Updater) downloadAndUpdate(versionInfo *VersionInfo) error {
|
||||
return fmt.Errorf("应用更新失败: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("✅ 更新成功,进程即将退出,等待系统服务重启...")
|
||||
slog.Info("更新成功,进程即将退出,等待系统服务重启...")
|
||||
|
||||
// 退出当前进程,让系统服务管理器(systemd/supervisor等)自动重启
|
||||
// 注意:这要求服务配置了自动重启(如 systemd 的 Restart=always)
|
||||
|
||||
Reference in new issue
Block a user