为什么SSH -t不等待后台进程?


13

为什么ssh -t不等待后台作业完成?

例:

ssh user@example 'sleep 2 &'

这可以按预期工作,因为ssh在2秒后返回,而

ssh user@example -t 'sleep 2 &'

不等待sleep完成并立即返回。

谁能解释这背后的原因?有没有办法让ssh -t所有后台进程完成后再返回?

我的用例是使用来启动一个脚本ssh -t,并且该脚本启动了一些后台作业,这些作业应在主脚本完成后仍然存在。随着ssh -t这是不可能的为止。

Answers:


22

如果没有-tsshdsleep通过两个管道获取远程shell(和子类,如)和stderr的标准输出(并通过另一个管道发送客户端的输入)。

sshd 确实会等待启动用户登录Shell的进程,而且还会在该进程终止后等待stdout管道上的eof(至少在openssh中不是stderr管道)。

当管道的写入端上没有打开任何进程的文件描述符时,就会发生eof,这通常仅在没有将其stdout重定向到其他进程的所有进程都消失时才会发生。

使用时-tsshd请勿使用管道。取而代之的是,使用一个伪终端对完成与远程外壳及其子级的所有交互(stdin,stdout,stderr)。

对于伪终端对,为了sshd与主端进行交互,没有类似的eof处理或任何方法来知道是否仍有进程向伪终端的从属端开放fds,因此它仅等待终止。它执行远程用户的登录shell,然后退出的过程。

在该出口处,pty对的主侧关闭,这意味着pty被破坏,因此由从属控制的进程将收到SIGHUP(默认情况下将终止它们)。


1
感谢您的彻底回答!我想知道的另一件事:伪终端退出后,所有后台进程都会终止吗?我正在启动的脚本启动了一项服务,该服务可与ssh配合使用。但是当使用ssh -t时,该服务未启动。似乎一旦ssh返回,服务就会关闭。
菲利普·穆里

实际上,伪终端的主端有一种方法可以知道何时所有从属文件描述符都已关闭。实际上,它关闭了所有终端的文件描述符后,由真实终端触发的机制相同。
JdeBP '17


@JdeBP,您愿意扩展吗?我不确定你是什么意思。AFAICT终端仿真器(xterm和侏儒末端至少)不关心仍然具有FDS打开到从进程当处理它们执行在管芯壳
斯特凡Chazelas

@PhilippMurry您可以nohup用来保持脚本那样运行。(您也可以考虑在其中启动长期运行的作业,tmux以便可以交互地监视其进度,但是日志文件可以正常工作。)
jpaugh

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.