![在哪些情况下,注销时不会向作业发送 SIGHUP?](https://linux22.com/image/45419/%E5%9C%A8%E5%93%AA%E4%BA%9B%E6%83%85%E5%86%B5%E4%B8%8B%EF%BC%8C%E6%B3%A8%E9%94%80%E6%97%B6%E4%B8%8D%E4%BC%9A%E5%90%91%E4%BD%9C%E4%B8%9A%E5%8F%91%E9%80%81%20SIGHUP%EF%BC%9F.png)
我读到一位用户的回答,他声称正在运行
foo 2>&1 >& output.log &
foo
即使他们注销也会继续运行。据该用户称,这甚至可以通过 SSH 连接进行。
我并不真的相信这一点,因为我的印象是,在与 SSH 断开连接或终止 TTY 的情况下,shell 及其进程将收到 SIGHUP,导致它们终止。根据我的假设,这是nohup
在这种情况下使用的唯一原因,或者tmux
,screen
等。
然后我调查了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