从ssh会话运行的程序是否取决于连接?


29

从ssh会话运行的程序是否取决于与客户端的连接?例如,当连接确实很慢时。因此,它是否主动等待直到在屏幕上打印出东西?

并且,如果它确实取决于连接,它是否还会在屏幕byobu上发生?由于有了这些,即使从主机断开连接,程序仍保持运行。


注意:我仅发现以下相关问题:


1
请注意,如果连接断开,该程序将继续运行直到会话超时(除非它停留在打印操作中),但是如果会话结束,该程序将正常终止。
塞布'16

Answers:


26

程序的输出被缓冲,因此,如果连接速度较慢,则当缓冲区已满时,程序将停止。

如果您使用的screen,它有一个缓冲,以及它使用尝试和显示器连接的会话。但是,如果不能足够快地更新远程终端,则不会停止在屏幕会话中连接的程序screen。就像连接断开时一样,程序继续填充screens缓冲区直到溢出(推出最旧的信息)。您看到的(可以滚动回)的内容取决于(仍然)该缓冲区中的内容。screen有效地将程序与终端(以及缓慢的SSH连接)分离。


9

如果基础TCP连接收到带有RST标志的数据包,则SSH连接可能过早死亡。如果一侧发送了一个数据包(可能是定期的SSH保持活动探测),但在合理的时间内未收到TCP确认,或者路由器确定连接的空闲时间过长,或者ISP只是邪恶。

在Unix终端模型中,当终端连接断开时,终端驱动程序将HUP信号发送到外壳,其终止还导致将SIGHUP发送到外壳中运行的进程。

Unix程序员常见问题解答中,项目1.15:

SIGHUP是一个信号,按照惯例,这意味着“终端线已挂断”。它与父进程无关,通常由tty驱动程序生成(并交付给前台进程组)。

但是,作为会话管理系统的一部分,恰好有两种情况在SIGHUP进程终止时发送:

  • 当死亡的进程是连接到终端设备的会话的会话负责人时,SIGHUP将发送到该终端设备的前台进程组中的所有进程。

  • 当一个进程死亡原因成为孤儿的进程组,和孤立组中的一个或多个进程被停止,然后 SIGHUPSIGCONT被送到孤儿组的所有成员。(孤立的进程组是其中组中没有进程具有父进程的父进程,该父进程属于同一会话,但不是同一进程组。)

SIGHUP默认信号处理程序是终止该过程:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process

但是,可以避免进程终止。

  • 您可以插入忽略SIGHUP的信号处理程序。要以用户身份进行操作,请将命令包装在中nohup。例如:

    nohup make all &
    
  • 您可以告诉外壳程序将其与子进程分离。例如,Bash有一个disown内置命令:

    make all
    

    CtrlZ

    bg
    disown %1
    

    然后,SIGHUP将不会传播到孩子(不再是孩子)。

  • 某些程序(尤其是守护程序)将自动使用上述机制:程序可以安装备用SIGHUP处理程序(使用sigaction(2)),或者可以选择加入新会话(setsid(2))。
  • 您可以运行screentmux,它分配一个伪TTY来运行与在SSH连接中断时未收到SIGHUP的shell的会话。SIGHUP不会从SSH会话中继到screen / tmux会话。

顺便说一句,处理不可靠的SSH连接的另一种方法是改用Mosh协议。Mosh在UDP上运行,因此不存在可能会被重置的TCP连接。



1

是的,通过SSH运行的程序将取决于其输出到某处。如果连接速度很慢,则输出必须在某个地方缓冲,并且缓冲区不能是无限的,因此,如果缓冲区已满,则程序必须阻塞。

请注意,输出不一定会发送到终端:考虑运行类似

ssh user@somewhere "cat file.txt" > file.txt

这实际上将复制文件。为此,cat的输出速率必须与连接的速率匹配:很明显,从中间丢失部分输出是不可接受的。

屏幕将改变这种情况,使其像终端一样,并保存应在“终端窗口”上显示的内容(加上向后滚动)。不需要记住程序输出的所有内容,只需记住适合“窗口”和回滚的部分即可。默认情况下,屏幕将等待慢速连接(阻止程序),但可以通过将“ nonblock on”设置为“ on”来检测卡住的连接。

从手册页:

无阻塞[on | off | numsecs]

告诉屏幕如何处理不再接受输出的用户界面(显示)。如果用户按^ S或TCP /调制解调器连接被断开但未收到挂断,则可能发生这种情况。如果nonblock处于关闭状态(这是默认设置),屏幕将等待直到显示重新开始以接受输出。如果nonblock处于打开状态,屏幕将等待直到达到超时(on视为1s)。如果显示器仍然不接收字符,屏幕将认为它已“阻塞”并停止向其发送字符。如果它在某个时间重新开始接受字符,屏幕将取消阻止显示并重新显示更新的窗口内容。

断开连接与慢速连接不同。纯SSH无法自动从中恢复,因此您的程序将收到SIGHUP。另一方面,屏幕将检测到断开连接,分离并退回到本地缓冲,直到重新连接屏幕为止。这不会阻止正在运行的程序。

(如果您运行类似irssi之类的东西会不断产生输出,但仍必须同时与网络进行通信,则设置nonblock 1您的位置.screenrc很重要。阻塞会导致与IRC断开连接,这非常烦人...)

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.