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