【问题标题】:When did HUP stop getting sent and what can I do about it?HUP 何时停止发送,我该怎么办?
【发布时间】:2014-02-13 04:20:51
【问题描述】:

在我年轻的时候,Unix 是新事物,创建一个在您退出时不会被杀死的进程是一项挑战。我们使用 nohup 命令保护我们的持久进程免受HUP 信号的影响。如果我们不小心,我们的进程会在我们注销时被杀死,甚至关闭我们启动它们的 shell。

快进到今天,我很惊讶默认设置似乎完全相反。在 Ubuntu 和 Red Hat 系统上,我发现我几乎可以将任何进程置于后台,杀死父 shell,注销,任何事情都可以继续进行。我在 Bash 脚本、Python 脚本和 C 程序中看到了相同的行为。我从 xterm 或 ssh 会话中得到相同的行为。

例如在 xterm 或 ssh 窗口中,键入:

while [ 1 ]; do date; sleep 10; done > /tmp/out &

现在从另一个窗口运行

tail -f /tmp/out

观察它每 10 秒打印一次日期,然后使用 Ctrl-D 关闭原始父 shell。仍在运行。注销并重新登录。仍在运行。

向它发送HUP 信号,它会立即死亡。

我可以通过 Python 脚本或 C 程序表现出相同的行为。睡不睡无所谓。例如,这个丑陋的 C 程序的行为是一样的:

#include <stdio.h>

void main() {
    while(1) {
        printf("*\n");
        fflush(stdout);
        int i, j, k = 0;
        for(i=0; i < 10000; i++) {
            for(j=0; j < 100000; j++) {
                k += i * j;
            }
        }
    }
}

这与我年轻时的生活方式完全背道而驰。我想我只是没有注意到它何时改变?有没有历史学家知道这是什么时候发生的? HUP 还会被用于此目的吗?

如果这确实是当前的状态,我的问题是:当用户注销或断开连接时,如何安排进程终止?

我有一个 hack,涉及观察 ppid(父 pid)的变化,但肯定有比这更优雅的东西。

【问题讨论】:

标签: linux bash shell signals


【解决方案1】:

我仍然收到 SIGHUP。一种简单的测试方法:

#!/usr/bin/env sh

echo "$$"
trap "echo HUPPED $$ > /tmp/willithup" HUP
sleep 1000

然后关闭终端模拟器。现在回到你的问题:

看它每 10 秒打印一次日期,然后关闭原始 使用 Ctrl-D 的父外壳。仍在运行。注销并重新登录。仍然 正在运行。

当父进程死亡时,进程不会获得 HUP。当它失去与控制终端的连接或当它被明确发送一个 HUP 时,它会得到一个 HUP。例如,当您注销 SSH 时会发生这种情况。

如果我们不小心,我们的进程会在我们登录时被杀死 关闭,甚至关闭我们启动它们的 shell

对于第二个:shell 本身可以在退出时向其所有子级发送 HUP。但是,例如 bash,默认情况下将 huponexit 设置为 false。这很可能已经改变了。请注意,无论 huponexit 选项如何,当它接收到 HUP 时,shell 也会向其所有子级发送 HUP


用史蒂文斯的话来说:

一个会话可以有一个控制终端。这通常是 终端设备(在终端登录的情况下)或伪终端 我们登录的设备(在网络登录的情况下)。

如果终端检测到调制解调器(或网络)断开连接 接口挂断信号被发送到控制进程( 会议负责人)。


为了进一步说明,初始 HUP 不是由 shell 发送的。它由终端驱动程序发送。之后,shell 将其“转发”给孩子们。所以确实,终端驱动程序发送的 HUP 可以“级联”。来自 TLPI:

当控制进程失去终端连接时,内核 向它发送一个 SIGHUP 信号以告知它这一事实。 (一个 SIGCONT 信号 也发送,以确保进程重新启动,以防万一 先前已被信号停止。)通常,这可能发生在两个 情况:

  • 当终端驱动程序检测到“断开连接”时,表示调制解调器或终端线路上的信号丢失。
  • 当工作站上的终端窗口关闭时。这是因为与终端窗口关联的伪终端的主端的最后一个打开文件描述符已关闭。

【讨论】:

  • 如果我在关闭终端模拟器之前把它放在后台,我不会。问题是关于在后台运行的进程。
  • @GaryBishop 您可以“在后台”运行它。只有当它失去与终端接口的连接时,它才会并且总是得到一个 HUP。
  • bash 颂歌不总是发送 HUP。根据我的经验,越来越多的系统关闭了huponexit
  • @JimB 仔细阅读我的回答。我从来没有说过 bash 发送 HUP。这是实际的终端线路驱动程序:-)
  • @JimB 我添加了来自 TLPI 的报价 :-)
【解决方案2】:

我相信您正在寻找huponexit shell 选项。您可以使用

轻松设置
$ shopt -s huponexit

bash 手册页中的一些详细信息:

shell 在收到 SIGHUP 后默认退出。前 退出时,交互式 shell 将 SIGHUP 重新发送到所有作业,正在运行 要么 停了下来。停止的作业被发送 SIGCONT 以确保它们收到 SIGHUP。防止外壳发送信号到 一个标准 特定的工作,它应该使用 disown 内置命令从工作表中删除(参见下面的 SHELL BUILTIN COMMANDS)或标记为不 收到 SIGHUP 使用 disown -h。

如果已使用 shopt 设置了 huponexit shell 选项,则当交互式登录 shell 退出时,bash 会向所有作业发送 SIGHUP。

【讨论】:

  • 此选项似乎解释了 xterms 和 ssh 的意外(对我而言)行为。谢谢!
猜你喜欢
  • 1970-01-01
  • 2014-04-15
  • 2015-09-20
  • 2016-02-06
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 2021-03-16
  • 1970-01-01
相关资源
最近更新 更多