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?
我想我可以解释一下吧!我不得不学习一些关于会话和进程组的内容,我在读了
The TTY Demystified.
因为没有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”
因为bash是以非交互模式开始的,这意味着默认情况下禁用作业控制,因此子进程与父bash进程(即会话引导者)处于同一进程组中.当父bash进程退出时,内核将发送SIGHUP到其进程组(位于前台),如setpgid(2)中所述:
相反,当使用交互式登录时,bash处于交互模式,这意味着默认情况下启用作业控制,因此子进程进入单独的进程组,并且在退出时不会收到SIGHUP. 我可以通过使用set -m来恢复我想要的行为,以启用bash中的作业控制.如果我将set -m添加到start.sh,那么当ssh退出时,这些子代不再被杀死. 神秘解决:) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |