nohup 和守护进程有啥区别?

Posted

技术标签:

【中文标题】nohup 和守护进程有啥区别?【英文标题】:What's the difference between nohup and a daemon?nohup 和守护进程有什么区别? 【发布时间】:2010-10-31 18:57:58 【问题描述】:

将脚本作为守护进程运行与使用 nohup 有何不同?

我知道在分叉进程等方面有什么区别,但这对我的脚本有什么影响?

【问题讨论】:

【参考方案1】:

成为守护进程

此链接列出了进程成为守护进程应采取的步骤:

https://web.archive.org/web/20120328110436/http://www.steve.org.uk/Reference/Unix/faq_2.html#SEC16

由于版权原因,我无法逐字复制列表(请参阅“关于”部分),但这里是摘要:

    fork(第一次)——所以我们不是组长,让家长退出。 致电setsid() -- 成为新会话的负责人。仅当我们不是组长时,此调用才有效。这个新会话没有控制终端。 fork(第二次)——所以我们不是会话负责人(因此无法重新获得控制终端),让父级退出。 cd 到根目录——所以我们不会阻止其他目录被卸载。 将umask 设置为所需值(可选)——因为我们可能继承了我们不想要的掩码。 关闭标准输入、标准输出、标准错误(或重新打开它们以指向其他地方)

nohup

nohup 做了什么:

如果 stdout 和 stderr 连接到终端,将它们重定向到 nohup.out 忽略 SIGHUP

异同

注意唯一常见的操作是如何重定向标准输出和标准错误。 成为守护进程甚至不需要忽略 SIGHUP。

nohup 不要求您使用“&”作为后台进程 - 这意味着您仍然可以使用 ctrl-c 发送 SIGINT。该进程仍然响应键盘输入。它也不会自动更改标准输入,因此建议您通过“< /dev/null”自行更改。

请不要将nohup 与通常与它一起使用的其他功能(例如背景)混淆。 OP专门询问了nohup

实践中

就实用性而言,当你想启动一个在 shell 退出时应该继续的一次性长时间运行的进程时,你会想要使用 nohup,但你也想将它与后台结合起来和重定向标准输入。一次性工作不值得制作守护进程,但守护进程的某些属性仍然可以用于 nohup 作业,例如“cd /”。

定期安排的定期任务最好通过cron(或其他一些调度程序)运行。

守护程序最适合监督没有可预测开始时间的重复任务。守护进程通常没有明确的结束时间(它由用户/另一个进程或系统关闭显式停止)。守护进程通常是响应应用程序(客户端)或其他条件(例如,通过 IO 设备通过 unix select() 传入的数据)的服务。其他守护进程轮询某个条件并执行相应操作。

关于控制终端的补充

见this page。简要总结一下,控制终端授予对其标准输入、标准输出、标准错误的无限制访问权限。只有一个进程组可以访问标准输入。默认情况下,后台进程组也可以写入stdout和stderr。

此外,发送到终端的键盘信号似乎只发送到将其作为控制终端的进程组。

【讨论】:

您的 steve.org.uk 链接已损坏。【参考方案2】:

nohup 命令是穷人将进程作为守护进程运行的方式。正如 Bruno Ranschaert 所指出的,当您在交互式 shell 中运行命令时,它有一个控制终端,并且在控制进程(通常是您的登录 shell)退出时会收到一个 SIGHUP(挂断)信号。 nohup 命令安排输入来自/dev/null,输出和错误都转到nohup.out,并让程序忽略中断、退出信号和挂断。它实际上仍然具有相同的控制终端 - 它只是忽略了终端控件。请注意,如果您希望进程在后台运行,您必须告诉 shell 在后台运行它 - 至少在 Solaris 上(也就是说,您输入“nohup sleep 20 &”;没有与号,进程同步运行在前台)。

通常,通过nohup 运行的进程需要时间,但不会等待来自其他地方的交互。

通常(这意味着如果你努力,你可以找到这些规则的例外),守护进程是潜伏在后台的东西,与任何终端断开连接,但等待响应某种输入。网络守护程序等待连接请求或 UDP 消息通过网络到达,执行适当的工作并再次发送回响应。例如,考虑 Web 服务器或 DBMS。

当一个进程完全守护自己时,它会经历nohup 代码所经历的一些步骤;它重新排列其 I/O,因此它不连接到任何终端,将自身与进程组分离,忽略适当的信号(这可能意味着它不会忽略任何信号,因为没有终端向它发送任何生成的信号通过终端)。通常,它分叉一次,并且父级成功退出。子进程通常在固定其进程组和会话 ID 等之后进行第二次分叉;然后孩子也退出了。孙子进程现在是自主的,不会显示在启动它的终端的 ps 输出中。

您可以查看 W Richard Stevens 和 Stephen A Rago 的 Advanced Programming in the Unix Environment, 3rd Edn,或 Marc J Rochkind 的 Advanced Unix Programming, 2nd Edn,了解有关守护进程的讨论。

我有一个程序daemonize,它将守护一个不知道如何(正确地)守护自己的程序。它是为解决程序中的缺陷而编写的,该程序本应自行守护但没有正确完成工作。如果需要,请与我联系 - 查看我的个人资料。

【讨论】:

不知道你为什么称它为穷人的。如果你想让你的进程成为一个守护进程,它会做正确的事情,除了它不会与控制终端断开连接,这在实践中并不重要。其次,你叫错了,正确的形式是(nohup sleep 20 &),即parens断开它与进程组负责人的连接,这样它就不会收到该进程组的信号。 @MaximYegorushkin 括号没有任何区别(据我所知)。从 shell 运行任何程序总是使该程序成为组长。试试这个,你会看到 PGID 总是匹配 PID:perl -e 'system "ps -fjp $$"'。此外,与号不是 nohup 所固有的,因此即使这也是 nohup 和守护程序之间的区别。我将用更多的差异添加我自己的答案。 @Kelvin:(nohup sleep 20 &) 中的括号确实有所作为。他们指定一个子外壳。在子 shell 内部,nohup 命令在后台执行sleep 命令。当它返回时,子 shell 退出,所以 sleep 是孤立的,不再由当前 shell '拥有'。 @JonathanLeffler 好的,我现在看到了不同之处——父 PID 是 1 而不是 shell 的 PID。但我仍然看不出成为流程组负责人有什么不同。它仍然是同一个会话的一部分,所以它不是完全“孤立的”。无论如何,括号似乎与 nohup/daemon 的区别无关。【参考方案3】:

守护进程无法启动,而 nohup 由用户启动。

【讨论】:

【参考方案4】:

在 UNIX 变体中,进程与终端进程(登录 shell)相关联。因此,当终端进程退出时,由于这种关联,进程也会停止。 nohup 可防止在终端停止时退出进程。

守护进程或恶魔是系统启动时启动的进程,它一直运行到关闭,没有用户明确要求它。因此,根据定义,它不是用户交互的一部分,而是属于系统。

如果您以用户身份访问系统,则可以使用 nohup。如果你是系统管理员,你可以安装一个守护进程。过程无所谓。

【讨论】:

+1 我的立场是正确的。在守护进程和后台进程 (&) 之间混淆。 :) 几乎正确。当控制进程(组长)退出组中的所有进程时,将发送 SIGHUP 可选地后跟 SIGCONT。 一些更正:守护进程不需要是系统进程;非特权用户可以运行守护程序。用户可以与守护进程交互,而不是通过终端信号和 IO 流(想想 Web 服务器)。几乎可以随时启动守护进程;它们不仅限于系统启动。

以上是关于nohup 和守护进程有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

关于守护进程和守护线程的区别

守护进程与守护线程的区别

Linux守护进程详解

守护进程 nohup

Php cli是守护进程的吗

5.1.14 守护线程