从SSH会话中断开连接是否会中止程序?

所以,说我开始rsynccp或任何其他可以长时间运行的命令后,我会从SSH会话断开连接。 这个命令是否继续运行,直到断开连接完成,或者只是被杀死?

总是想知道这一点。

编辑2016年:

这个问答早于systemd v230的崩溃 。 从systemd v230开始,新的默认设置是终止终止login会话的所有子节点,而不pipe采取什么历史上有效的预防措施来防止这种情况发生。 可以通过在/etc/systemd/logind.conf设置KillUserProcesses=no来改变行为,或者在用户空间中使用systemd特有的机制来启动一个守护进程。 这些机制不在这个问题的范围之内。

下面的文本描述了UNIXdevise空间中传统的工作方式比Linux存在的时间更长。


他们会被杀死,但不一定立即。 这取决于SSH守护进程需要多长时间才能确定您的连接已经死亡。 接下来的是一个更长的解释,将帮助你理解它是如何工作的。

login后,SSH守护程序会为您分配一个伪terminal,并将其附加到您的用户configuration的loginshell。 这被称为控制terminal。 每一个在这个阶段正常启动的程序,无论多深层次的shell,最终都会“追溯其祖先”回到shell。 你可以用pstree命令来观察这个。

当与您的连接关联的SSH守护程序进程确定您的连接已经死亡时,它会向loginshell发送一个挂断信号( SIGHUP )。 这通知你已经消失的shell,它应该开始清理自己; 在这一点上发生了什么是特定于shell的(search其“HUP”的文档页面),但是在终止之前,大多数情况下它将开始发送SIGHUP以运行与之关联的作业。 反过来,每个进程都将完成他们在接收到该信号时所做的任何configuration。 通常这意味着终止。 如果这些工作有自己的工作,信号也往往会传递。

在控制terminal挂起的过程中,这些过程是从terminal(你开始的守护进程)或者用前缀nohup命令调用的terminal。 (即“不要挂在这个”)

terminal多路复用器是在断开连接之间保持shell环境完整的常用方式。 它们允许你脱离你的shell进程,以便以后可以重新连接到它们,不pipe这个断开是偶然的还是故意的。 tmuxscreen是比较stream行的。 使用它们的语法超出了你的问题的范围,但它们值得深入研究。


有人要求我详细说明“SSH守护程序需要多长时间才能确定您的连接已经死亡”。 这是特定于SSH守护进程的每个实现的行为,但您可以指望所有这些行为在任一方重置TCP连接时终止。 如果任一方尝试写入套接字并且TCP数据包未被确认,则这将快速发生,或者如果双方都不试图写入PTY,则会发生缓慢。

在这个特定的背景下,最有可能触发写作的因素是:

  • 一个进程(通常是前台的进程)试图写入服务器端的PTY。 (服务器 – >客户端)
  • 用户试图写在客户端的PTY。 (客户端 – >服务器)
  • Keepalives任何forms。 这些通常不是由客户端或服务器默认启用的,通常有两种风格:应用程序级别和基于TCP(即SO_KEEPALIVE )。 Keepalive相当于服务器或客户端不经常发送数据包到另一端,即使没有其他的事情会有任何理由写入套接字。 虽然这通常是为了防止超时连接的防火墙,但是它还有一个副作用,即当发送方没有响应时,发送方会注意到这个副作用。

TCP会话的通常规则适用于此处:如果客户端和服务器之间的连接中断,但双方都不会在问题发生期间尝试发送数据包,则只要双方都事后响应,并且接收到预期的TCP序列号。

如果一方已经确定套接字已经死了,那么效果通常是即时的:sshd进程将发送HUP并自行终止(如前所述),否则客户端会通知用户检测到的问题。 值得注意的是,仅仅因为一方认为另一方已经死亡并不意味着另一方已经被告知这一点,并且通常会保持开放,直到它试图写入连接或者从另一方接收到TCP重置。 (如果连接可用的话)

正如其他人所提到的,一旦你从ssh断开连接的任何东西都不见了。

正如@Michael Hampton等人所提到的,你可以使用诸如tmux或者screen tmux工具来断开/重新连接到terminal而不会丢失其内容(即subprocess)。

另外,您可以使用&符号将进程置于后台,然后使用disown命令将其与当前shell分离。

 # start a command % sleep 5000 & [1] 3820 # check it % jobs [1]+ Running sleep 5000 & # disown everything % disown -a # check it again (gone from shell) % jobs % # but it's still running on the system % ps -eaf|grep "[s]leep" saml 3820 23791 0 00:16 pts/1 00:00:00 sleep 5000 % 

不,任何仍然附着在terminal上的程序,并没有像nohup那样放在后台,将会被杀死。

这就是为什么有像tmux这样的虚拟terminal解决scheme,以及即使断开连接也可以继续运行的会话,而且以后可以重新连接的旧式screen