从 ssh 会话运行的程序是否依赖于连接?

从 ssh 会话运行的程序是否依赖于连接?

从 ssh 会话运行的程序是否依赖于与客户端的连接?例如,当连接速度非常慢时。那么它会主动等待直到屏幕上打印出内容吗?

如果它确实取决于连接,那么它也会发生吗屏幕或者屏风例如?因为有了这些,即使在与主机断开连接后,程序仍会保持运行。


注意:我只找到这些相关问题:

答案1

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

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

答案2

如果底层 TCP 连接收到带有以下内容的数据包,则 SSH 连接可能会过早终止:快速恢复时间旗帜。如果一侧发送数据包(可能是定期的 SSH keepalive 探测)但在合理的时间内没有收到 TCP 确认,或者路由器确定连接空闲时间过长,或者如果ISP 只是作恶。

在 Unix 终端模型中,当终端连接断开时,终端驱动程序会发送一个HUP信号到 shell,其终止还会导致向 shell 中运行的进程发送 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 &
    
  • 您可以告诉 shell 将子进程与其分离。例如,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 通过 UDP 运行,因此不存在有重置风险的 TCP 连接。

答案3

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

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

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

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

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

从手册页:

非块 [on|off|numsecs]

告诉屏幕如何处理停止接受输出的用户界面(显示)。如果用户按 ^S 或 TCP/调制解调器连接被切断但未收到挂断信号,则可能会发生这种情况。如果非阻塞关闭(这是默认设置),屏幕将等待显示器重新启动以接受输出。如果非阻塞打开,屏幕将等待,直到达到超时(打开被视为 1 秒)。如果显示器仍然没有接收到字符,屏幕将认为它“被阻止”并停止向其发送字符。如果在某个时候它重新启动以接受字符,屏幕将解锁显示并重新显示更新的窗口内容。

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

(如果你运行像 irssi 这样的东西,它会不断产生输出,但仍然必须同时与网络通信,那么nonblock 1在你的设置中就很重要。阻塞会导致与 IRC 断开连接,这是非常烦人的......).screenrc

相关内容