Linux HUP什么时候停止被发送的?我能做些什么?

Linux HUP什么时候停止被发送的?我能做些什么?,linux,bash,shell,signals,Linux,Bash,Shell,Signals,回到我年轻的时候,Unix是一个新事物,创建一个进程,在您注销时不会被杀死,这是一个挑战。我们使用nohup命令保护持久进程不受HUP信号的影响。如果我们不小心,我们的进程将在注销时被终止,甚至关闭启动它们的shell 快进到今天,我发现违约似乎恰恰相反,这让我感到惊讶。在Ubuntu和Red Hat系统上,我发现我几乎可以将任何进程放在后台,杀死父shell,注销,任何事情,它都可以继续运行。我在Bash脚本、Python脚本和C程序中看到了相同的行为。我从xterm或ssh会话中获得相同的行

回到我年轻的时候,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;
            }
        }
    }
}
#包括
void main(){
而(1){
printf(“*\n”);
fflush(stdout);
int i,j,k=0;
对于(i=0;i<10000;i++){
对于(j=0;j<100000;j++){
k+=i*j;
}
}
}
}
这与我年轻时的生活方式完全背道而驰。我想我只是没注意到它什么时候变了?有历史学家知道这是什么时候发生的吗?
HUP
是否已被用于此目的

如果这确实是当前的情况,我的问题是:当用户注销或断开连接时,我如何安排进程死亡?


我有一个黑客程序,包括观察
ppid
(父pid)的变化,但肯定有比这更优雅的东西

我还是会叹口气。一种简单的测试方法:

#!/usr/bin/env sh

echo "$$"
trap "echo HUPPED $$ > /tmp/willithup" HUP
sleep 1000
然后关闭终端仿真器。现在回到你的问题:

观看它每10秒打印一次日期,然后关闭原件 Ctrl-D的父shell。仍在运行。注销并重新登录。仍然 跑步

当其父进程死亡时,该进程不会获得HUP。当它与控制终端失去连接或显式发送HUP时,它将获得HUP。例如,当您注销SSH时,就会发生这种情况

如果我们不小心,当我们登录时,我们的进程将被杀死 关闭,甚至关闭我们启动它们的外壳

对于第二个:shell本身可以在退出时向其所有子级发送HUP。但是,例如bash在默认情况下将
huponexit
设置为false。这很可能就是发生了变化的原因。请注意,不管huponexit选项是什么,当shell接收到HUP时,它也会将HUP发送给它的所有子级


用史蒂文斯的话说:

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

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


为了进一步澄清,最初的HUP不是由壳牌公司发送的。它由终端驱动程序发送。之后,贝壳“转发”给孩子们。因此,终端驱动程序发送的HUP确实可以“级联”。从TLPI:

当控制进程失去其终端连接时,内核 向其发送一个SIGHUP信号以通知此事实。(A)SIGCONT信号 也会发送,以确保在发生错误时重新启动进程 通常情况下,这可能发生在两种情况下 情况:

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

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

$ shopt -s huponexit
bash手册页中的一些详细信息:

shell在收到SIGHUP后默认退出。之前 退出时,一个交互式shell会重新向所有作业发送消息,并运行 或 停止。停止的作业被发送SIGCONT以确保它们收到SIGHUP。防止外壳将信号发送到 标准杆- 对于特定作业,应使用disown内置命令(参见下面的SHELL内置命令)将其从作业表中删除,或将其标记为not 接收 使用disown-h进行SIGHUP

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


我不知道在关闭终端模拟器之前是否将其放在后台。问题是关于在后台运行的进程。@GaryBishop您可以“在后台”运行它。当它失去与终端接口的连接时,它只会并且总是得到一个HUP。bash odes并不总是发送一个HUP。根据我的经验,越来越多的系统关闭了
huponexit
。@JimB仔细阅读我的答案。我从来没说过bash会发脾气。这是实际的终端线驱动程序:-)@JimB我添加了一个来自TLPI的引用:-)huponexit是一个bash选项这个选项似乎可以解释xterms和ssh的意外行为。谢谢