与SSH断开连接时,tmux会话被杀死


23

摘要:我试图弄清楚为什么我从ssh断开连接后,tmux会话会死掉

详细资料

我在Arch Linux系统上安装了tmux。当我启动tmux会话时,我可以从中分离出来,然后在ssh会话处于活动状态时再次附加。但是,如果我结束ssh会话,则tmux会话将被杀死。

我知道这不是正常的行为,因为即使ssh会话已结束,我也有其他系统在其中tmux会话继续运行,并且可以在建立新的ssh连接后附加到tmux会话。有问题的系统和可以正常工作的系统具有非常相似的配置,因此我不确定要检查什么。

我正在运行tmux 1.9a版本。有问题(我具有root用户访问权限)的系统具有3.17.4-1的Linux内核版本,而工作正常的系统具有3.16.4-1-ARCH的内核(我没有root权限)系统)。我怀疑内核版本是否是问题的根源,那只是我注意到的一个区别。

我想问一下是否有人遇到过类似的问题并知道可能的解决方案。

导致问题的确切步骤是:

  1. SSH到机器
  2. 运行tmux以启动tmux
  3. ctrl-B D 分离(此时我可以重新连接 tmux attach
  4. 关闭ssh会话(此时tmux会话已终止,当我以root身份登录到另一个终端时,已经能够观察到此情况)
  5. 与SSH重新连接并运行tmux attach,我得到消息no sessions和运行tmux ls返回failed to connect to server: Connection refused。这是有道理的,因为服务未运行。对我来说没有意义的是为什么当我从ssh会话断开连接时,它在步骤4中被杀死。

跟踪数据:

作为对其中一项评论的回应,我使用了strace来查看什么系统调用了tmux服务器进程。当我退出ssh会话(通过键入exit或使用ctrl-d)时,tmux进程被杀死了。这是strace输出的最后一部分。

poll([{fd=4, events=POLLIN}, {fd=11, events=POLLIN}, {fd=6, events=POLLIN}], 3, 424) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=1, si_uid=0} ---
sendto(3, "\17", 1, 0, NULL, 0)         = 1
+++ killed by SIGKILL +++

我将其与tmux正常工作的另一个系统进行了比较,即使在退出后,tmux进程仍在该系统上继续运行。因此,根本原因似乎是当我关闭ssh会话时tmux进程被终止了。我需要花一些时间来解决这个问题,以找出原因,但是我认为我会更新我的问题,因为strace建议很有用。


可以肯定的是,请分步描述:我假设您使用ssh,启动tmux会话,从该会话分离并关闭shh:再次使用ssh时,您没有任何重新加入tmix会话的方法吗?即,该会话不再运行?
Olivier Dulac 2014年

@OlivierDulac是的,您的假设是正确的。我还编辑了我的问题,以包括这些详细信息。
加布里埃尔南部

您如何关闭ssh会话?您可以在ssh的pid上附加一个strace,在ssh的pid上附加一个strace,以查看在关闭ssh连接时它是否收到东西(非常冗长,重定向到文件)
Olivier Dulac 2014年

@OlivierDulac感谢您的建议。我已经使用strace中的信息更新了问题。结束ssh会话后,tmux服务器进程似乎被杀死。我不认为这会发生,所以我需要弄清楚为什么会发生。
加布里埃尔南部

在启用详细日志记录的情况下启动tmux,然后查看断开连接时是否将任何内容打印到日志中。另外,进出tmux的远程计算机上的TERM是什么?
jasonwryan 2014年

Answers:


16

理论

一些包括systemd的初始化系统提供了杀死所有属于该服务的进程的功能。该服务通常启动一个流程,该流程通过分叉创建更多流程,这些流程也可以这样做。通常将所有此类过程视为服务的一部分。在systemd中,这是使用cgroups完成的。

在systemd中,默认情况下,当服务停止时,属于该服务的所有进程都将被杀死。SSH服务器显然是服务的一部分。当您连接到服务器时,SSH服务器通常会分叉,新进程将处理您的SSH会话。通过从SSH会话进程或其子进程派生,其他服务器端进程将启动,包括您的screentmux

Killmode和套接字激活

可以使用KillMode伪指令更改默认行为。上游项目不包含任何.service文件,因此这些文件因分发而异。通常,有两种方法可以在系统上启用SSH。一种是经典的方法ssh.service,它可以维持长时间运行的SSH守护程序在网络上的侦听。另一个是通过套接字激活处理的,该套接字激活ssh.socket反过来启动sshd@.service,仅针对单个SSH会话运行。

解决方案

如果您的进程在会话结束时被杀死,则可能是您正在使用套接字激活,当它注意到SSH会话进程已退出时,被systemd杀死了。在这种情况下,有两种解决方案。一种是通过使用ssh.service而不是来避免使用套接字激活ssh.socket。另一种是设置KillMode=processService一节ssh@.service

KillMode=process设置对于经典服务器可能也很有用ssh.service,因为它避免了在服务器停止或重新启动时终止SSH会话进程或屏幕tmux进程。

未来笔记

这个答案显然获得了一定程度的普及。虽然它适用于OP,但由于systemd-logind 开发或配置,将来可能不适用于某人。如果您遇到的行为不同于此答案中的描述,请检查有关登录会话的文档。


来自下降投票者的任何具体反馈还是只是拖钓?
2014年

3
感谢您的详细回复。切换到sshd.service可以解决此问题。
2015年

我在使用init而不是的系统上遇到此问题systemd。但这还是有点不同,请参阅我的问题
Gerrit

5

您是否将systemd与套接字激活一起用于SSH?

如果是这样,则存在一个已知问题。根据systemd的支持者所说,这实际上是一个功能-当会话终止时,systemd杀死会话产生的所有进程。(我看到它很有用,但是在GNU screentmux情况下,您当然希望☺,当然,在大多数其他情况下,用户可能会运行后台进程。)

如果是这样,请尝试从切换sshd.socketsshd.service


1
我要说的是,如果允许用户运行注销后运行的进程,则通常不希望将该功能用于SSH登录。这不是特定于屏幕或tmux,而是特定于SSH(服务器端具有任何后台进程)。
帕维尔·希默达(PavelŠimerda)

2
@PavelŠimerda是的,我认为它是隐式的,但现在对其进行了编辑以使其更加明确。
mirabilos 2014年

3

我在Ubuntu 16.04(kde neon)上的tmux和屏幕遇到了相同的问题。当ssh会话断开时,屏幕/ tmux被终止。

长话短说,systemd将其默认设置更改为killuserprocess = yes,因此在离开ssh会话后,由它创建的每个进程都将终止。

使用此命令轻松修复(经过数小时的尝试)运行screen / tmux

对于屏幕

systemd-run --scope --user screen

用于Tmux

systemd-run --scope --user tmux

您可以创建别名以使其更容易

alias tmux= "systemd-run --scope --user tmux"


-bash: systemd-run: command not foundRed Hat Enterprise Linux Server release 6.8 (Santiago)
Gerrit

如果我还没有扎根,这行得通吗?
Gerrit

1
我注意到在Ubuntu 18.04 LTS(仅16.04)上不会发生不希望的tmux /屏幕杀死行为。
赛斯

2

不需要从迁移sshd.socket到的另一种解决方案sshd.service是将tmux服务器作为systemd服务[0]启动。这样,tmux当您通过SSH进入服务器时,该服务器已经在运行,而不是由tmuxSSH中的命令生成,因此不会被杀死。

[0] https://wiki.archlinux.org/index.php/tmux#Autostart_with_systemd


如果我还没有扎根,这行得通吗?
Gerrit

是的,这是一个有效的解决方案。但是您仍然想通过在SSH会话上重新启动SSH服务来解决这种情况。:)
PavelŠimerda'16

伙计们,如果您使用OpenRC,我制作了一个tmux初始化脚本,该脚本与ArchWiki中提到的服务文件相同
Megver83,

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.