在哪些情况下,当您注销时,SIGHUP 不会发送到作业?

slh*_*hck 13 ssh signals tty

我读了一个声称正在运行的用户的答案

foo 2>&1 >& output.log &
Run Code Online (Sandbox Code Playgroud)

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

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

然后我查看了glibc 的手册

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

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

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

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

令我更加困惑的是,我运行了一个交互式 Zsh 会话,运行yes >& /dev/null &并输入了exit,当 Zsh 警告我有正在运行的作业时,exit第二次输入后,它告诉我它已经 SIGHUPed 一个作业。在 Bash 中执行完全相同的操作会使工作继续运行……

Rap*_*ens 22

Bash 似乎SIGHUP只有在它自己收到 a 时才会发送SIGHUP,例如,当虚拟终端关闭或 SSH 连接中断时,就会发生这种情况。从文档

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

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

您可以强制 Bash 警告您仍在运行后台进程的事实

shopt -s checkjobs
Run Code Online (Sandbox Code Playgroud)

SIGHUP如果您在交互式 shell 中,则可以选择在退出时发送(请参阅此处)。但它在我的装有 Bash 4.2.25 的机器上不起作用。也许它对你有用

shopt -s huponexit
Run Code Online (Sandbox Code Playgroud)

  • 那么,当 SSH 连接中断时,会发送“SIGHUP”,否则,干净退出后作业会继续运行?这解释了我所看到的。 (3认同)
  • [`huponexit` “仅对交互式登录 shell 有效”](http://lists.gnu.org/archive/html/bug-bash/2009-03/msg00091.html) (2认同)