我有一个嵌入式系统,在上面执行telnet
,然后在后台运行应用程序:
./app_name &
现在,如果我关闭终端并在其他终端上执行
telnet
,并且进行检查,则可以看到此过程仍在运行。为了检查这一点,我编写了一个小程序:
#include<stdio.h>
main()
{
while(1);
}
我在后台在本地linux PC中运行了该程序,然后关闭了终端。
现在,当我从其他终端检查此过程时,我发现该过程也被杀死。
我的问题是:
最佳答案
谁应该杀死工作?
通常,前台和后台作业在不同情况下会被内核或 shell 程序发送的SIGHUP
杀死。
内核何时发送SIGHUP
?
内核将SIGHUP
发送到controlling process:
真实(硬件)终端的
内核将
SIGHUP
发送到其他进程组:当控制进程终止时,
通常,控制过程是您的 shell 。因此,总结一下:
当真正或伪终端断开/关闭时,
SIGHUP
发送到 shell ; SIGHUP
发送到前台进程组。 SIGHUP
发送到孤立的进程组。 请注意,如果内核不包含停止的进程,则它不会将
SIGHUP
发送到后台进程组。bash
何时发送SIGHUP
?Bash将
SIGHUP
发送到所有作业(前景和背景):SIGHUP
时,它是一个交互式 shell 程序(并且在编译时启用了作业控制支持); huponexit
选项(并且在编译时启用了作业控制支持)。 查看更多详细信息here。
笔记:
bash
不会将SIGHUP
发送到使用disown
从作业列表中删除的作业; nohup
开始的SIGHUP
。 更多详细信息here。
那其他 shell 呢?
通常,shell传播
SIGHUP
。在普通导出生成SIGHUP
的情况比较少见。Telnet或SSH
在telnet或SSH下,关闭连接时(例如,在PC上关闭
telnet
窗口时)将发生以下情况:SIGHUP
发送到bash
; bash
接收SIGHUP
,将SIGHUP
发送给所有作业并终止; SIGHUP
并终止。 问题
我可以使用
bash
或telnetd
SSH服务器上的busybox
和dropbear
重现您的问题:有时,关闭客户端连接后,后台作业不会收到SIGHUP
(并且不会终止)。当服务器(
telnetd
或dropbear
)关闭pty的主服务器端时,似乎出现竞争条件:bash
接收SIGHUP
并立即终止后台作业(如预期的那样)并终止; bash
在处理EOF
之前会检测pty的从属端上的SIGHUP
。 当
bash
检测到EOF
时,默认情况下它将立即终止而不发送SIGHUP
。后台作业仍在运行!解
也可以将
bash
配置为在正常导出(包括SIGHUP
)上发送EOF
:bash
作为登录shell启动。 huponexit
works仅用于登录 shell AFAIK。登录 shell 通过
-l
中的argv[0]
选项或leading hyphen启用。您可以配置telnetd
来运行/bin/bash -l
或更好的/bin/login
,后者在登录Shell模式下调用/bin/sh
。例如。:
telnetd -l/bin/登录
huponexit
选项。例如。:
shopt -s huponexit
每次在
bash
session 中键入此内容,或将其添加到.bashrc
或/etc/profile
中。 种族为什么会发生?
bash
仅在安全时取消阻止信号,并在信号处理程序无法安全中断某些代码段时阻止它们。此类关键部分会不时调用中断点,并且如果在执行关键部分时收到信号,则会延迟其处理程序,直到发生下一个中断点或退出关键部分为止。
您可以从源代码中的
quit.h
开始挖掘。因此,在我们的情况下,似乎
bash
有时在关键部分中会收到SIGHUP
。 SIGHUP
处理程序的执行被延迟,并且bash
读取EOF
并终止,然后退出关键部分或调用下一个中断点。引用
官方Glibc手册中的