diff --git a/agent/logger.go b/agent/logger.go index 228fb53..8b51a95 100644 --- a/agent/logger.go +++ b/agent/logger.go @@ -48,7 +48,7 @@ func (f *CustomFormatter) Format(entry *logrus.Entry) ([]byte, error) { return []byte(msg), nil } -func initLogger(logFile string) { +func initLogger(logFile string, fileOnly bool) { logDir := filepath.Dir(logFile) if logDir != "" && logDir != "." { os.MkdirAll(logDir, 0755) @@ -65,10 +65,11 @@ func initLogger(logFile string) { Compress: false, } - // daemon 模式下只输出到文件,避免重复日志 - if isDaemon { + // fileOnly 模式下只输出到文件(daemon 模式或重启模式) + if fileOnly { log.SetOutput(lumberjackLogger) } else { + // 前台运行时同时输出到终端和文件 log.SetOutput(io.MultiWriter(os.Stdout, lumberjackLogger)) } } diff --git a/agent/main.go b/agent/main.go index 705b428..5632dea 100644 --- a/agent/main.go +++ b/agent/main.go @@ -59,6 +59,8 @@ func main() { } case "-d", "--daemon": isDaemon = true + case "--restart": + isRestart = true } } @@ -128,6 +130,9 @@ func printUsage() { // daemon 模式标记 var isDaemon = false +// 是否从 daemon 重启(用于自动更新后重启) +var isRestart = false + func cmdStart() { // 检查是否已经在运行 pid := readPidFile() @@ -143,7 +148,7 @@ func cmdStart() { } // 以下是 daemon 子进程的逻辑 - initLogger(logFile) + initLogger(logFile, true) config := &Config{Interval: 30} if err := loadConfigFile(configFile, config); err != nil { @@ -193,14 +198,17 @@ func cmdStart() { // cmdRun 前台运行 func cmdRun() { - // 检查是否已经在运行 - pid := readPidFile() - if pid != 0 && isProcessRunning(pid) { - fmt.Printf("Agent 已在运行 (PID: %d)\n", pid) - return + // 检查是否已经在运行(重启模式下跳过检查) + if !isRestart { + pid := readPidFile() + if pid != 0 && isProcessRunning(pid) { + fmt.Printf("Agent 已在运行 (PID: %d)\n", pid) + return + } } - initLogger(logFile) + // 重启模式下只输出到文件(因为是从 daemon 进程 exec 过来的) + initLogger(logFile, isRestart) config := &Config{Interval: 30} if err := loadConfigFile(configFile, config); err != nil { diff --git a/agent/update.go b/agent/update.go index b82789b..5ba2d58 100644 --- a/agent/update.go +++ b/agent/update.go @@ -144,13 +144,18 @@ func (a *Agent) restart() { basePath = strings.TrimSuffix(basePath, ".bak") } + // 删除 PID 文件,避免新进程检测到旧 PID 而拒绝启动 + removePidFile() + if runtime.GOOS == "windows" { // Windows: 启动新进程后退出 cmd := exec.Command(basePath, "start") cmd.Start() os.Exit(0) } else { - // Linux/macOS: 使用 exec 替换当前进程 - syscall.Exec(basePath, []string{basePath, "start"}, os.Environ()) + // Linux/macOS: 使用 exec 替换当前进程,直接运行(不需要 daemon) + // 因为 syscall.Exec 会替换当前进程,当前进程本身就是 daemon + // --restart 标记告诉新进程这是重启,只输出到文件 + syscall.Exec(basePath, []string{basePath, "run", "--restart"}, os.Environ()) } }