如果我们关闭启动它的终端,Linux会杀死后台进程吗? [英] Does linux kill background processes if we close the terminal from which it has started?

查看:643
本文介绍了如果我们关闭启动它的终端,Linux会杀死后台进程吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个嵌入式系统,在该系统上执行telnet,然后在后台运行一个应用程序:

I have an embedded system, on which I do telnet and then I run an application in background:

./app_name &

现在,如果我关闭终端并在其他终端上执行telnet,如果我检查了一下,便可以看到此过程仍在运行.

Now if I close my terminal and do telnet from other terminal and if I check then I can see this process is still running.

要对此进行检查,我编写了一个小程序:

To check this I have written a small program:

#include<stdio.h>
main()
{
    while(1);
}

我在后台的本地linux PC中运行了该程序,然后关闭了终端.

I ran this program in my local linux pc in background and I closed the terminal.

现在,当我从其他终端检查此过程时,我发现该过程也被杀死了.

Now, when I checked for this process from other terminal then I found that this process was also killed.

我的问题是:

  • 为什么相同类型的过程具有未定义的行为?
  • 它依赖于什么?
  • 它取决于Linux版本吗?

推荐答案

谁应该杀死工作?

通常,前台和后台作业会在不同情况下被内核或外壳程序发送的SIGHUP杀死.

内核SIGHUP发送到 控制过程 :

Kernel sends SIGHUP to controlling process:

  • 对于真实(硬件)终端:在终端驱动程序中检测到断开连接时,例如在调制解调器线路挂断时;
  • 用于伪终端(pty):当关闭引用pty主节点的最后一个描述符时,例如当您关闭终端窗口时.
  • for real (hardware) terminal: when disconnect is detected in a terminal driver, e.g. on hang-up on modem line;
  • for pseudoterminal (pty): when last descriptor referencing master side of pty is closed, e.g. when you close terminal window.

内核SIGHUP发送到其他进程组:

Kernel sends SIGHUP to other process groups:

  • 控制进程终止时,
  • 进入前景进程组
  • 孤立的进程组 ,当它成为孤立的并且已停止成员时.
  • to foreground process group, when controlling process terminates;
  • to orphaned process group, when it becomes orphaned and it has stopped members.

控制过程是建立与控制终端的连接的会话负责人.

Controlling process is the session leader that established the connection to the controlling terminal.

通常,控制过程是您的外壳.因此,总结一下:

Typically, the controlling process is your shell. So, to sum up:

    当真正或伪终端断开/关闭时,
  • 内核将SIGHUP发送到外壳;
  • 当外壳终止时,
  • 内核将SIGHUP发送到前台进程组;
  • 内核将SIGHUP发送到孤立的进程组(如果它包含已停止的进程).
  • kernel sends SIGHUP to the shell when real or pseudoterminal is disconnected/closed;
  • kernel sends SIGHUP to foreground process group when the shell terminates;
  • kernel sends SIGHUP to orphaned process group if it contains stopped processes.

请注意,如果内核不包含停止的进程,则不会将SIGHUP发送到后台进程组.

Note that kernel does not send SIGHUP to background process group if it contains no stopped processes.

Bash SIGHUP发送到所有作业(前景和背景):

Bash sends SIGHUP to all jobs (foreground and background):

  • 当它收到SIGHUP并且是交互式外壳程序时(并且在编译时启用了 job control 支持);
  • 退出时,它是一个交互式登录外壳,并设置了huponexit选项(并且在编译时启用了 job control 支持).
  • when it receives SIGHUP, and it is an interactive shell (and job control support is enabled at compile-time);
  • when it exits, it is an interactive login shell, and huponexit option is set (and job control support is enabled at compile-time).

此处查看更多详细信息.

注意:

  • bash SIGHUP发送到使用disown从作业列表中删除的作业;
  • 使用nohup ignore SIGHUP开始的进程.
  • bash does not send SIGHUP to jobs removed from job list using disown;
  • processes started using nohup ignore SIGHUP.

更多详细信息此处.

通常,shell传播SIGHUP.在普通出口生成SIGHUP的情况较少.

Usually, shells propagate SIGHUP. Generating SIGHUP at normal exit is less common.

在telnet或SSH下,关闭连接时(例如,在PC上关闭telnet窗口时),应该发生以下情况:

Under telnet or SSH, the following should happen when connection is closed (e.g. when you close telnet window on PC):

  1. 客户端被杀死;
  2. 服务器检测到客户端连接已关闭;
  3. 服务器关闭pty的主服务器端;
  4. 内核检测到主pty已关闭,并将SIGHUP发送给bash;
  5. bash接收SIGHUP,将SIGHUP发送给所有作业并终止;
  6. 每个作业接收SIGHUP并终止.
  1. client is killed;
  2. server detects that client connection is closed;
  3. server closes master side of pty;
  4. kernel detects that master pty is closed and sends SIGHUP to bash;
  5. bash receives SIGHUP, sends SIGHUP to all jobs and terminates;
  6. each job receives SIGHUP and terminates.


问题

我可以使用bashtelnetdbusyboxdropbear SSH服务器重现您的问题:有时,后台作业不会收到SIGHUP(并且不会终止)关闭客户端连接.


Problem

I can reproduce your issue using bash and telnetd from busybox or dropbear SSH server: sometimes, background job doesn't receive SIGHUP (and doesn't terminate) when client connection is closed.

当服务器(telnetddropbear)关闭pty的主服务器端时,似乎出现了竞赛条件:

It seems that a race condition occurs when server (telnetd or dropbear) closes master side of pty:

  1. 通常,bash接收到SIGHUP并立即终止后台作业(如预期的那样)并终止;
  2. 但有时,bash在处理SIGHUP之前在pty 的从属端检测到EOF.
  1. normally, bash receives SIGHUP and immediately kills background jobs (as expected) and terminates;
  2. but sometimes, bash detects EOF on slave side of pty before handling SIGHUP.

bash检测到EOF时,默认情况下它将立即终止而不发送SIGHUP.后台作业仍在运行!

When bash detects EOF, it by default terminates immediately without sending SIGHUP. And background job remains running!

也可以将bash配置为在正常出口(包括EOF)上发送SIGHUP:

It is possible to configure bash to send SIGHUP on normal exit (including EOF) too:

  • 确保bash作为登录外壳启动. huponexit 有效仅适用于登录Shell AFAIK.

  • Ensure that bash is started as login shell. The huponexit works only for login shells, AFAIK.

通过-l选项或

Login shell is enabled by -l option or leading hyphen in argv[0]. You can configure telnetd to run /bin/bash -l or better /bin/login which invokes /bin/sh in login shell mode.

例如:


telnetd -l /bin/login

  • 启用huponexit选项.

    例如:

    
    shopt -s huponexit
    

    每次在bash会话中键入此内容,或将其添加到.bashrc/etc/profile.

    Type this in bash session every time or add it to .bashrc or /etc/profile.

    bash仅在安全的情况下取消阻止信号,并在信号处理程序无法安全中断某些代码段的情况下阻止它们.

    bash unblocks signals only when it's safe, and blocks them when some code section can't be safely interrupted by a signal handler.

    此类关键部分会不时调用中断点,如果在执行关键部分时收到信号,则其处理程序将延迟到下一个中​​断点发生或关键部分已退出.

    Such critical sections invoke interruption points from time to time, and if signal is received when a critical section is executed, it's handler is delayed until next interruption point happens or critical section is exited.

    您可以从 quit.h 开始挖掘在源代码中.

    You can start digging from quit.h in the source code.

    因此,在我们的案例中,bash有时在关键部分中有时会收到SIGHUP. SIGHUP处理程序执行被延迟,并且bash读取EOF并在退出关键部分或调用下一个中断点之前终止.

    Thus, it seems that in our case bash sometimes receives SIGHUP when it's in a critical section. SIGHUP handler execution is delayed, and bash reads EOF and terminates before exiting critical section or calling next interruption point.

      官方Glibc中的
    • 作业控制" 部分手册.
    • "Linux编程接口"一书的第34章进程组,会话和作业控制".
    • "Job Control" section in official Glibc manual.
    • Chapter 34 "Process Groups, Sessions, and Job Control" of "The Linux Programming Interface" book.

    这篇关于如果我们关闭启动它的终端,Linux会杀死后台进程吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆