Answers:
如果基础TCP连接收到带有RST标志的数据包,则SSH连接可能过早死亡。如果一侧发送了一个数据包(可能是定期的SSH保持活动探测),但在合理的时间内未收到TCP确认,或者路由器确定连接的空闲时间过长,或者ISP只是邪恶。
在Unix终端模型中,当终端连接断开时,终端驱动程序将HUP信号发送到外壳,其终止还导致将SIGHUP发送到外壳中运行的进程。
从Unix程序员常见问题解答中,项目1.15:
SIGHUP
是一个信号,按照惯例,这意味着“终端线已挂断”。它与父进程无关,通常由tty驱动程序生成(并交付给前台进程组)。但是,作为会话管理系统的一部分,恰好有两种情况在
SIGHUP
进程终止时发送:
当死亡的进程是连接到终端设备的会话的会话负责人时,
SIGHUP
将发送到该终端设备的前台进程组中的所有进程。当一个进程死亡原因成为孤儿的进程组,和孤立组中的一个或多个进程被停止,然后
SIGHUP
和SIGCONT
被送到孤儿组的所有成员。(孤立的进程组是其中组中没有进程具有父进程的父进程,该父进程属于同一会话,但不是同一进程组。)
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将不会传播到孩子(不再是孩子)。
sigaction(2)
),或者可以选择加入新会话(setsid(2)
)。screen
或tmux
,它分配一个伪TTY来运行与在SSH连接中断时未收到SIGHUP的shell的会话。SIGHUP不会从SSH会话中继到screen / tmux会话。顺便说一句,处理不可靠的SSH连接的另一种方法是改用Mosh协议。Mosh在UDP上运行,因此不存在可能会被重置的TCP连接。
是的,通过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断开连接,这非常烦人...)