当生成长时间运行的子进程时,确保它们在主进程的生命周期之外生存至关重要,特别是当由 systemd 管理时。在某些情况下,子进程可能会意外终止,从而导致关键后台任务未处理。
尝试使用 go 编程语言创建启动子进程的主进程时遇到以下问题:
package main import ( "log" "os" "os/exec" "syscall" "time" ) func main() { if len(os.Args) == 2 && os.Args[1] == "child" { for { time.Sleep(time.Second) } } else { cmd := exec.Command(os.Args[0], "child") cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true} log.Printf("child exited: %v", cmd.Run()) } }
从终端执行此程序时,即使主进程停止或终止(Ctrl Z 和kill -INT 7914),子进程仍然存在。但是,当主进程作为 systemd 服务启动时,子进程也会突然终止。
要解决此问题,请修改 systemd 服务文件 (/etc/systemd/system/exectest.service),添加以下行:
KillMode=process
此设置指示 systemd 仅终止主进程,允许子进程继续运行。默认情况下,systemd 使用控制组模式,该模式会杀死与主进程在同一控制组内的所有进程。
更新后的 systemd 服务文件:
[Unit] Description=ExecTest [Service] Type=simple ExecStart=/home/snowm/src/exectest/exectest User=snowm KillMode=process [Install] WantedBy=multi-user.target
经过此修改,子进程将在主进程终止后继续存在,保证后台任务的稳定性和连续性。
以上是如何防止 systemd 在父进程终止时杀死子进程?的详细内容。更多信息请关注PHP中文网其他相关文章!