注销时,SIGHUP在什么情况下不发送到作业?


10

我从一个声称正在跑步的用户那里得到了一个答案

foo 2>&1 >& output.log &

foo即使他们注销也将导致继续运行。根据该用户的说法,这甚至可以通过SSH连接工作。

我真的不相信,因为我的印象是,在断开与SSH的连接或终止TTY的情况下,shell及其进程将收到SIGHUP,从而导致它们终止。这一点,我的假设下,被使用的唯一理由nohup在这样的情况下,或者tmuxscreen等。

然后,我查看了glibc的手册

该信号还用于向与该会话相关联的作业报告终端上控制过程的终止;该终止有效地断开了会话中的所有进程与控制终端的连接。

这似乎证实了我的想法。但进一步看,它说

如果进程是具有控制终端的会话领导者,则将SIGHUP信号发送到前台作业中的每个进程,并且将控制终端与该会话解除关联。

那么,这是否意味着放在后台的作业将不会收到SIGHUP?

令我进一步困惑的是,当Zsh警告我我正在运行作业时,我进行了一个交互式Zsh会话,yes >& /dev/null &并键入exit,然后再次键入后exit,告诉我说它已经完成了一项工作。在Bash中执行完全相同的操作会使工作继续进行……


过去,我遇到过服务器问题,该服务器由于ssh突然断开连接,并且我的进程一直在运行,但是没有任何tty关联,所以我不得不再次登录并发送SIGHUP / TERM / KILL结束它们。因此,遵循相同的逻辑,我刚刚进行了测试,输入logoutyes仍在运行。
Braiam

除了是否发送SIGHUP之外,进程是否定义了信号处理程序(并捕获了SIGHUP)或信号掩码是发送该信号时是否终止的其他因素。因此,仅因为注销后它仍在运行并不意味着它没有发送该信号
Tim B

您是否在指这个问题:serverfault.com/questions/115999/…?似乎在这里找到了答案-默认情况下,RedHat没有设置shopt。这是RedHat的特殊配置怪癖。
鲍里斯·伯科夫

@Bob不,我以前没有看过,但这是一个很好的资源。谢谢!
slhck

很高兴它有所帮助。实际上,拉斐尔也提到了这个问题。
鲍里斯·伯科夫

Answers:


18

Bash似乎SIGHUP仅在自身接收到a的情况下发送SIGHUP,例如在关闭虚拟终端或SSH连接中断时发生。从文档中

默认情况下,在收到SIGHUP后,shell退出。退出之前,交互式外壳程序将SIGHUP重新发送给所有正在运行或已停止的作业。已停止的作业将发送给SIGCONT,以确保它们收到了SIGHUP。为防止外壳程序将SIGHUP信号发送到特定作业,应使用内置的disown将其从作业表中删除(请参阅内置的Job Control),或使用disown -h将其标记为不接收SIGHUP。

因此,如果您键入exit或按Ctrl+,D将保留所有后台进程,因为这不会向Bash发送挂断信号。

您可以强制Bash向您警告有关仍然存在正在运行的后台进程的事实。

shopt -s checkjobs

SIGHUP如果您处于交互式外壳中,则可以选择发送退出出口(请参见此处)。但是在使用Bash 4.2.25的计算机上它不起作用。也许对你有用

shopt -s huponexit

那么,当SSH连接中断时,SIGHUP将发送该消息,否则,通过干净的退出,作业是否继续运行?那解释了我所看到的。
slhck

是。仅在特殊情况下,当与用户的连接中断时,挂断信号才出现。
拉斐尔·阿伦斯



@npostavs感谢您将我添加到答案中的信息。
拉斐尔·阿伦斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.