从SSH会话断开连接会杀死您的程序吗?


87

所以,说我得到断开从SSH会话,我已经开始之后rsync或者cp或任何其他命令可长时间运行。在断开连接后该命令是否一直运行直到完成,还是被杀死?

一直在想这个。


我只是想补充一下以上内容,如果您发现自己需要将已经在运行的进程放入其中的情况screen,请尝试reptyr
一位可悲的家伙,

它将杀死您的程序。如果您要通过SSH将操作系统版本从Ubuntu 16.04更新到17.10,则非常烦人
kurdtpage,

Answers:


118

编辑2016年:

此问答早于系统化的v230故障。从systemd v230开始,新的默认设置是杀死终止登录会话的所有子级,无论采取了什么历史上有效的预防措施来防止这种情况。该行为可以通过设置来改变KillUserProcesses=no/etc/systemd/logind.conf,或使用systemd特异性机制用于开始在用户空间守护程序规避。这些机制不在此问题的范围内。

下面的文字描述了传统上在UNIX设计空间中工作比Linux更长的时间。


他们将被杀死,但不一定立即被杀死。这取决于SSH守护程序确定您的连接已失效所需的时间。接下来是一个更长的解释,可以帮助您了解其实际工作原理。

登录时,SSH守护程序为您分配了一个伪终端,并将其附加到用户配置的登录Shell中。这称为控制终端。到那时,您正常启动的每个程序,无论有多深的Shell层,最终都会将其祖先追溯到该Shell。您可以使用pstree命令来观察。

当与您的连接关联的SSH守护进程确定您的连接已死时,它将向SIGHUP登录shell 发送一个挂断信号()。这会通知您已消失的外壳,并且外壳应自行清理。此时发生的事情是特定于shell的(在其文档页面上搜索“ HUP”),但是在大多数情况下,它将SIGHUP终止之前开始发送到与其关联的正在运行的作业。这些进程中的每一个都将在接收到该信号后执行它们配置为执行的任何操作。通常这意味着终止。如果这些工作有自己的工作,那么信号也常常会传递出去。

在控制终端挂断后幸存的进程要么是使自己脱离拥有终端的进程(您在终端内部启动的守护进程),要么是使用前缀nohup命令调用的进程。守护进程以不同的方式解释HUP信号(即“不要挂断”)。由于它们没有控制终端,并且不会自动接收HUP信号,因此,管理员将其重新用作手动请求以重新加载配置。具有讽刺意味的是,这意味着大多数管理员直到很久以后才了解非守护程序对该信号的“挂断”用法。这就是为什么您正在阅读本文!

终端多路复用器是在断开连接之间保持外壳环境完整的一种常用方法。它们使您能够以某种方式从Shell进程中分离出来,以便以后可以重新连接到它们,而无论断开是偶然还是有意进行的。tmux并且screen是更受欢迎的;使用它们的语法超出了您的问题范围,但是值得研究。


有人要求我详细说明SSH守护程序确定您的连接已失效需要多长时间。这是特定于SSH守护程序的每种实现的一种行为,但是您可以指望当任一方重置TCP连接时,它们全部终止。如果服务器尝试写入套接字且未确认TCP数据包,则将快速发生这种情况;如果没有尝试写入PTY的情况,则将缓慢发生这种情况。

在这种特定情况下,最有可能触发写操作的因素是:

  • 试图写入服务器端PTY的进程(通常是前台的进程)。(服务器->客户端)
  • 用户尝试在客户端上写入PTY。(客户端->服务器)
  • 任何形式的Keepalive。默认情况下,客户端或服务器通常不会启用这些功能,通常有两种形式:应用程序级别和基于TCP的(即SO_KEEPALIVE)。即使当没有其他理由没有理由向套接字写入消息时,Keepalive很少会向服务器或客户端发送数据包到另一侧。虽然这通常是为了使防火墙过分超时而导致防火墙超时,但它具有副作用,使发送方注意到另一端的响应速度没有那么快。

TCP会话的通常规则适用于此:如果客户端和服务器之间的连接中断,但是在出现问题期间双方均未尝试发送数据包,则只要双方随后做出响应并接收到预期的TCP,连接将继续存在序列号。

如果一方确定套接字已死,则效果通常是立竿见影的:sshd进程将发送HUP并自行终止(如前所述),或者客户端将检测到的问题通知用户。值得注意的是,仅仅因为一方认为另一方已死并不意味着已通知另一方。连接的孤立端通常将保持打开状态,直到它尝试对其进行写操作并超时,或者从另一端收到TCP重置。(如果当时连接可用)仅在服务器注意到后,才进行此答案中所述的清除。


3
我还要在该列表中添加“ dtach”命令-与screen / tmux相反,它可以让您将多个终端连接到一个会话,并且对于延长会话时间也很有用,尽管它不会提供重播最近历史的任何方法。
蓬松的

dtach网址是:dtach.sourceforge.net
slm

1
极好的解释。我已经感觉更多linuxey了!
fregas 2013年

3
另外,尽管从技术上讲,这不是您的答案的一部分,但这里有一些有趣的琐事:您可以kill -HUP以root身份使用来强制某人的终端挂断。没有充分的理由,您不应该这样做。当用户在维护期间让Shell运行时,我大部分精力都花在了上面,我需要卸载一个文件系统,使他们的Shell保持打开状态。如果用户已连接但最终处于空闲状态,则将信号发送到他们的sshd进程。否则,如果它在终端多路复用器内部运行,请将其发送到您要停止的shell。只挂壳会让您无法工作!
安德鲁B

@AndrewB,能否请您详细说明“ SSH守护进程...如何确定您的连接已死”?以及我怎么知道SSH守护进程是否认为/知道(哪个)连接已死?
小鹏-ZenUML.com 2016年

22

正如其他人提到的那样,一旦您与ssh断开连接,其中运行的任何内容都将消失。

正如@Michael Hampton和其他人提到的那样,您可以使用诸如tmuxscreen断开/重新连接终端的工具,而不会丢失其内容(即子进程)。

另外,您可以使用&符将进程置于后台&,然后使用命令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
%

是否可以将终端会话重新附加到disowned进程?
假名称

4
是。有关详细信息,请参见此
slm

13

不,仍然附在终端上的任何程序,如果未使用诸如之类的东西放置在后台nohup,都将被杀死。

这就是为什么存在虚拟终端解决方案(例如tmux和或更老的)screen会创建即使在您断开连接后仍继续运行并可以在以后重新连接的会话的原因。

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.