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

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

我读到一位用户的回答,他声称正在运行

foo 2>&1 >& output.log &

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

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

然后我调查了glibc 的手册:

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

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

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

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

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

答案1

Bash 似乎SIGHUP仅在自身收到 时才会发送SIGHUP,例如,当虚拟终端关闭或 SSH 连接中断时会发生这种情况。来自文档:

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

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

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

shopt -s checkjobs

SIGHUP如果您处于交互式 shell 中,可以选择在退出时发送消息(看这里)。但它在我的 Bash 4.2.25 机器上不起作用。也许它适合你

shopt -s huponexit

相关内容