在与同事进行了长时间的讨论后,我提出这个问题,我真的很想得到澄清。
我启动了一个后台进程,方法是将“ &
”附加到命令行,或者使用CTRL-Z
“ ”停止它并在后台恢复它bg
。然后我注销。
会发生什么?
我们非常确定它应该被 SIGHUP 杀死,但这并没有发生;再次登录后,该进程正常运行,并pstree
显示它已被“采纳” init
。
这是预期的行为吗?
但是,如果是,那么该nohup
命令的目的是什么?看起来,不管有没有该命令,该进程无论如何都不会被终止……
编辑1
更多细节:
- 该命令是从 SSH 会话启动的,而不是从物理控制台启动的。
- 命令已启动没有
nohup
和/或&
;然后它被暂停CTRL-Z
并在后台恢复bg
。 - ssh 会话没有删除。确实有一个注销(“
exit
”命令)。 - 该过程是一个
scp
文件复制操作。 - 再次登录后,
pstree
显示该进程正在运行并且是 的子进程init
。
编辑2
更清楚地陈述问题:将一个进程置于后台(使用&
或bg
)是否会使其忽略SIGHUP
,就像nohup
命令一样?
编辑3
我尝试手动发送一个SIGHUP
到scp
:它退出了,所以它肯定不会忽略信号。
然后我尝试再次启动它,将其置于后台并注销:它被“采用”init
并继续运行,当我重新登录时我发现它在那里。
我现在很困惑。看来SIGHUP
注销时根本没有发送任何消息。
答案1
找到答案。
对于 BASH,这取决于huponexit
shell 选项,可以使用内置shopt
命令查看和/或设置。
看起来这个选项默认是关闭的,至少在基于 RedHat 的系统上是这样。
更多信息BASH 手册页:
默认情况下,shell 在收到 SIGHUP 后退出。在退出之前,交互式 shell 会将 SIGHUP 重新发送给所有正在运行或已停止的作业。已停止的作业将收到 SIGCONT 以确保它们收到 SIGHUP。要防止 shell 向特定作业发送信号,应使用 disown 内置命令将其从作业表中删除(请参阅下面的 SHELL 内建命令),或使用 disown -h 将其标记为不接收 SIGHUP。
如果已使用 shopt 设置了 huponexit shell 选项,则当交互式登录 shell 退出时,bash 会向所有作业发送 SIGHUP。
答案2
我同意 Warner 的观点,只是想补充一点,你可以使用内置的“disown”命令阻止 shell 发送 SIGHUP。bash 手册页中有很好的描述。
答案3
您可以使用命令禁止启动命令并将输出重定向到 nohup 输出文件。来自 nohup 手册页:
nohup - run a command immune to hangups, with output to a non-tty
另一个选择是使用屏幕命令。使用 screen 的好处是您可以稍后重新连接到该进程。
答案4
如果您注销(Ctrl-D或exit
),它将继续运行。但如果您关闭终端窗口,后台进程将收到SIGHUP
。如果您失去与服务器的连接,它们也会收到SIGHUP
。本地运行的 shell 也是如此(只是您不能失去与本地 shell 的连接)。