bash – 为什么ssh等待我的subshel​​l没有-t,并用-t杀死他们?

前端之家收集整理的这篇文章主要介绍了bash – 为什么ssh等待我的subshel​​l没有-t,并用-t杀死他们?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个bash脚本start.sh,看起来像这样:
for thing in foo bar; do
    {
        background_processor $thing
        cleanup_on_exit $thing
    } &
done

这样做我想要的:我运行start.sh,它退出代码0,并且两个subshel​​l运行在后台.每个subshel​​l运行background_processor,当它退出时,它运行cleanup_on_exit.即使我退出我最初运行start.sh的终端(即使是ssh连接)也是如此.

然后我试过这个:

ssh user@host "start.sh"

除此之外,start.sh已经退出,ssh显然也等待子shell退出.我真的不明白为什么一旦start.sh退出,subhells成为pid 1的孩子,他们甚至没有分配一个tty …所以我不明白他们如何仍然与我的ssh连接相关联.

后来我试过:

ssh -t user@host "start.sh"

现在这些进程有一个分配的伪tty.现在,我发现一旦start.sh退出,ssh就会退出,但它也会杀死子进程.

我猜到在后一种情况下,子进程正在发送SIGHUP,所以我这样做:

ssh -t user@host "nohup start.sh"

这实际上有用!所以,我有一个解决我的实际问题的解决方案,但我想在这里了解SIGHUP / tty的细节.

总之,我的问题是:

>为什么ssh(没有-t)等待子进程即使在start.sh退出之后,即使它们有父pid 1?
>为什么ssh(with -t)杀死子进程,显然是用SIGHUP,即使从终端运行终端并注销该终端也不会发生这种情况?

我想我可以解释一下吧!我不得不学习一些关于会话和进程组的内容,我在读了 The TTY Demystified.
  1. Why does ssh (without -t) wait for the child processes even after start.sh exits,even though they have parent pid 1?

因为没有tty,ssh通过管道(然后由孩子继承)连接到shell进程的stdin / stdout / stderr,而我正在使用的OpenSSH版本(OpenSSH_4.3p2)等待这些套接关闭退出.一些较早版本的OpenSSH没有这样做.有一个很好的解释,有理由,here.

相反,当使用交互式登录(或ssh -t)时,ssh和进程正在使用TTY,因此没有管道等待.

我可以通过重定向流来恢复我想要的行为.该变体立即返回:ssh user @ host“start.sh< / dev / null> / dev / null 2>& 1”

  1. Why does ssh (with -t) kill the child processes,apparently with a SIGHUP,even though that does not happen when I run them from a terminal and log out of that terminal?

因为bash是以非交互模式开始的,这意味着默认情况下禁用作业控制,因此子进程与父bash进程(即会话引导者)处于同一进程组中.当父bash进程退出时,内核将发送SIGHUP到其进程组(位于前台),如setpgid(2)中所述:

If a session has a controlling terminal,… [and] the session leader exits,the SIGHUP signal will be sent to each process in the foreground process group of the controlling terminal.

相反,当使用交互式登录时,bash处于交互模式,这意味着默认情况下启用作业控制,因此子进程进入单独的进程组,并且在退出时不会收到SIGHUP.

我可以通过使用set -m来恢复我想要的行为,以启用bash中的作业控制.如果我将set -m添加到start.sh,那么当ssh退出时,这些子代不再被杀死.

神秘解决:)

猜你在找的Bash相关文章