HUP何时停止发送,我该怎么办?

问题描述:

早在我年轻的时候,Unix就是新事物,创建一个流程,当您注销时,而不是被杀死是一个挑战。我们使用nohup命令来保护我们的持续进程不受HUP信号的影响。如果我们不小心,当我们注销时,我们的进程会被杀死,甚至关闭我们从中启动它们的shell。HUP何时停止发送,我该怎么办?

快进到今天,我发现我很惊讶默认看起来完全相反。在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。仍在运行。注销并返回。仍在运行。

发送它一个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甚至可以用于此目的吗?

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

我有一个黑客,涉及到ppid(父pid)来改变,但肯定有一些比这更优雅。

+0

huponexit是我做不成的bash选项http://stackoverflow.com/questions/4298741/how-bash-handles-the-jobs-when-logout – JimB

我相信你正在寻找huponexit shell选项。在收到SIGHUP的

shell退出默认:您可以

$ shopt -s huponexit 

一些从bash的手册页的细节很容易设置此。在 退出之前,交互式shell将SIGHUP重新发送到所有作业,运行 或 停止。停止的工作发送SIGCONT以确保他们收到SIGHUP。为了防止shell将信号发送到特定的作业,应该使用disown内建函数从作业表中删除它(请参阅下面的SHELL BUILTIN COMMANDS)或者将其标记为 接收 SIGHUP使用disown -h。

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

+0

此选项似乎解释了两个人的意外(对我)行为xterms和ssh。谢谢! – GaryBishop

我仍然得到SIGHUP。一个简单的测试方法:

#!/usr/bin/env sh 

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

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

看着它每10秒打印一次日期,然后用Ctrl-D关闭原始的 父壳。仍在运行。注销并返回。仍然 正在运行。

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

如果我们不小心,我们的流程会被杀掉的,当我们登录 关,甚至是封闭式的,我们开始他们

对于第二个外壳:外壳本身可以当HUP退出时向其所有儿童发送HUP。但是,例如,bash默认情况下将huponexit设置为false。这很可能是变化的。请注意,无论huponexit选项如何,在收到HUP时也会向其所有子项发送一个HUP。


在史蒂文斯的话:

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

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


为了进一步阐明,初始HUP不被壳发送。它由终端驱动程序发送。之后,贝壳“转发”给孩子们。确实,终端驱动程序发送的HUP可以“级联”。从TLPI:

当控制过程失去其终端连接,内核 将其发送SIGHUP信号以通知它这个事实。 (A SIGCONT信号 也被发送,以确保该过程被重新启动的情况下,它已经 被信号先前停止。)典型地,这可以在两个 情况下发生:

  • 当“断开”由终端驱动程序检测到,指示调制解调器或终端线路上的信号丢失。
  • 在工作站上关闭终端窗口时。发生这种情况是因为与终端窗口关联的伪终端的主侧的最后一个打开文件描述符被关闭。
+0

如果我把它在后台关闭之前终端仿真器。问题是关于在后台运行的进程。 – GaryBishop

+0

@GaryBishop你可以在后台运行它。只有当它失去与终端接口的连接时,它才会始终获得HUP。 – cnicutar

+0

bashö不*总是*发送HUP。根据我的经验,越来越多的系统关闭了“huponexit”。 – JimB