fix: 使用 setsid 确保重启命令独立于父进程执行

问题原因:
- cmd.Start() 启动的子进程与父进程在同一会话中
- 当 systemctl restart 发送 SIGTERM 给父进程时
- 子进程可能也会被终止,导致重启命令无法完成

修复内容:
- 使用 setsid 创建新会话,子进程完全独立于父进程
- 分离标准输入/输出/错误流
- 确保即使父进程被 kill,重启命令仍能执行完成
This commit is contained in:
shaw
2025-12-18 20:00:53 +08:00
parent 4eaa0cf14a
commit f0e89992f7

View File

@@ -67,7 +67,17 @@ func RestartService() error {
// The sub2api user has NOPASSWD sudo access for systemctl commands // The sub2api user has NOPASSWD sudo access for systemctl commands
// (configured by install.sh in /etc/sudoers.d/sub2api). // (configured by install.sh in /etc/sudoers.d/sub2api).
// Use -n (non-interactive) to prevent sudo from waiting for password input // Use -n (non-interactive) to prevent sudo from waiting for password input
cmd := exec.Command(sudoPath, "-n", systemctlPath, "restart", serviceName) //
// Use setsid to create a new session, ensuring the child process
// survives even if the parent process is killed by systemctl restart
setsidPath := findExecutable("setsid")
cmd := exec.Command(setsidPath, sudoPath, "-n", systemctlPath, "restart", serviceName)
// Detach from parent's stdio to ensure clean separation
cmd.Stdin = nil
cmd.Stdout = nil
cmd.Stderr = nil
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
return fmt.Errorf("failed to initiate service restart: %w", err) return fmt.Errorf("failed to initiate service restart: %w", err)
} }