【发布时间】:2011-03-06 22:49:54
【问题描述】:
我正在编写一个 Linux 守护程序。我找到了两种方法。
- 通过调用
fork()并设置sid来守护进程。 - 使用
&运行您的程序。
哪种方法是正确的?
【问题讨论】:
-
你可以使用 nohup:stackoverflow.com/questions/958249/…
我正在编写一个 Linux 守护程序。我找到了两种方法。
fork() 并设置sid 来守护进程。& 运行您的程序。哪种方法是正确的?
【问题讨论】:
来自http://www.steve.org.uk/Reference/Unix/faq_2.html#SEC16
以下是成为守护进程的步骤:
- fork() 以便父级可以退出,这会将控制权返回给调用程序的命令行或 shell。此步骤是必需的,以便保证新流程不是流程组负责人。如果您是流程组负责人,下一步 setid() 将失败。
- setsid() 成为进程组和会话组组长。由于控制终端与会话相关联,而这个新会话尚未获得控制终端,我们的进程现在没有控制终端,这对守护进程来说是件好事。
- fork() 再次让父级(会话组负责人)可以退出。这意味着我们作为非会话组长,永远无法重新获得控制终端。
- chdir("/") 以确保我们的进程不会保留任何正在使用的目录。不这样做可能会导致管理员无法卸载文件系统,因为它是我们的当前目录。 [等效地,我们可以更改为包含对守护程序的操作很重要的文件的任何目录。]
- umask(0) 这样我们就可以完全控制我们编写的任何内容的权限。我们不知道我们可能继承了什么 umask。 [这一步是可选的]
- close() fds 0、1 和 2。这将释放我们从父进程继承的标准输入、输出和错误。我们无法知道这些 fd 可能被重定向到哪里。请注意,许多守护程序使用 sysconf() 来确定限制 _SC_OPEN_MAX。 _SC_OPEN_MAX 告诉您最大打开文件/进程。然后在一个循环中,守护进程可以关闭所有可能的文件描述符。您必须决定是否需要这样做。如果您认为可能有文件描述符打开,您应该关闭它们,因为并发文件描述符的数量是有限制的。
- 为标准输入、标准输出和标准错误建立新的开放描述符。即使您不打算使用它们,打开它们仍然是一个好主意。这些的精确处理是一个品味问题。例如,如果您有一个日志文件,您可能希望将其作为标准输出或标准错误打开,并将“/dev/null”作为标准输入打开;或者,您可以将“/dev/console”作为标准错误和/或标准输出打开,将“/dev/null”作为标准输入,或任何其他对您的特定守护进程有意义的组合。
更好的是,只需调用daemon() 函数(如果可用)。
【讨论】:
我建议根本不要将您的程序编写为守护程序。使用给定的文件描述符、当前目录、进程组等使其在前台运行。
如果您想将该程序作为守护进程运行,请使用 start-stop-daemon(8)、init(8)、runsv(来自 runit)、upstart、systemd 或其他任何方式将您的进程作为守护进程启动。也就是说,让您的用户决定如何运行您的程序,而不是强制它必须作为守护程序运行。
【讨论】:
只需使用daemon(3)(来自unistd.h)。
daemon() 函数用于程序 想要脱离 控制终端并在 背景作为系统守护进程。 ...
【讨论】:
export BUILD_ID=dontKillMe daemon flask run
第一个。第二个不是守护进程,而是在后台运行。守护程序应该在自己的会话和进程组中,并且应该不有控制终端。
【讨论】:
实际上要创建一个守护进程,你必须双叉。
使用 & 运行程序会使 shell 在后台运行程序,这不会使其成为守护进程。守护进程有 init (pid 1) 作为父进程,这就是需要双叉的原因。
因此,如果您的程序是守护程序,那么做事的好方法是自己处理这个问题(还有更多方法,请参阅here)。您也可以使用 start-stop-daemon 程序。
【讨论】:
fork() 两次。 stackoverflow.com/questions/881388/…
您使用什么语言?一些语言有辅助方法,使守护进程更容易。例如,Ruby 有 daemons 包。
【讨论】: