我已经多次尝试让程序在 Linux 下作为守护进程运行。
- 在一种情况下,我刚刚使用了
daemon()
. - 还有一次,我编写了自己的守护程序代码 ( based on something like this ),因为我想对 STDIN、STDOUT 等进行更复杂的重定向。
- 我还使用过 Busybox
start-stop-daemon
将 C# Mono 程序作为守护进程启动,并使用-m
选项生成 PID 文件。
问题是,所有这些解决方案都在 PID 文件创建上存在竞争条件,也就是说,PID 文件是由程序在前台进程退出后的某个不确定时间由其后台进程写入的。这是一个问题,例如在嵌入式 Linux 中,如果程序由 initscript 启动,最后启动一个看门狗进程,该进程通过检查其 PID 文件来监视程序的运行情况。在使用 start-stop-daemon
的 C# Mono 情况下,我的系统偶尔会在看门狗启动时重新启动,因为当时程序的 PID 文件尚未写入看门狗进程开始监视(令人惊讶的是,这可能会在实际场景中发生)。
如何在没有 PID 文件竞争条件的情况下对程序进行守护进程?即通过这样的方式保证前台进程退出时PID文件被完全创建并写入有效的PID值。
注意,使用 Linux 守护进程 fork-setsid-fork idiom (to prevent the daemon from acquiring a controlling tty) 会使这变得更加困难。 ,因为父级无法轻易获取孙子级的 PID。
最佳答案
正如您所发现的,管理自己的 pid 文件的守护进程本质上是很活泼的。解决方案是不要守护进程,而是在前台运行进程,然后使用进程管理程序来管理它。例如runit , supervisord ,和systemd's support for "new-style daemons" .
关于Linux 守护进程没有 PID 文件竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36489529/