摘要:我试图弄清楚为什么我的 tmux 会话在我与 ssh 断开连接时会死掉
详情:
我在 Arch Linux 系统上安装了 tmux。当我开始一个 tmux 会话时,我可以从它分离,然后在 ssh 会话处于活动状态时再次附加。但是如果我结束我的 ssh 会话,那么 tmux 会话就会被杀死。
我知道这不是正常行为,因为我有其他系统,即使 ssh 会话结束,tmux 会话也会继续运行,并且我可以在建立新的 ssh 连接后附加到 tmux 会话。有问题的系统和正常工作的系统具有非常相似的配置,所以我不确定要检查什么。
我正在运行 tmux 1.9a 版。有问题的系统(我有 root 访问权限)的 Linux 内核版本为 3.17.4-1,而正常工作的系统的内核版本为 3.16.4-1-ARCH(我没有 root 权限)系统)。我怀疑内核版本是问题的根源,但这只是我注意到的一个差异。
我想我会问是否有人见过类似的问题并知道可能的解决方案。
导致问题的确切步骤是:
tmux
以启动 tmuxctrl-B D
分离(此时我可以重新连接 tmux attach
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 +++
Run Code Online (Sandbox Code Playgroud)
我将此与 tmux 正常工作的不同系统进行了比较,并且在该系统上,即使我退出后,tmux 进程仍继续运行。所以根本原因似乎是当我关闭 ssh 会话时 tmux 进程正在终止。我需要花一些时间来解决这个问题以找出原因,但我想我会更新我的问题,因为 strace 建议很有用。
Pav*_*rda 17
包括 systemd 在内的一些 init 系统提供了一个功能来终止属于该服务的所有进程。该服务通常会启动单个进程,该进程通过分叉创建更多进程,这些进程也可以这样做。所有这些过程通常被视为服务的一部分。在 systemd 中,这是使用cgroups完成的。
在 systemd 中,当服务默认停止时,属于服务的所有进程都会被杀死。SSH 服务器显然是服务的一部分。当您连接到服务器时,SSH 服务器通常会分叉并且新进程处理您的 SSH 会话。通过从 SSH 会话进程或其子进程分叉,其他服务器端进程将启动,包括您的screen或tmux。
可以使用KillMode
指令更改默认行为。上游项目不包含任何.service
文件,因此这些文件因发行版而异。通常有两种方法可以在您的系统上启用 SSH。一个是ssh.service
维护一个长时间运行的 SSH 守护进程监听网络的经典。另一种是通过套接字激活,由ssh.socket
它依次启动sshd@.service
,它只为单个 SSH 会话运行。
如果您的进程在会话结束时被杀死,则可能是您正在使用套接字激活,并且当 systemd 注意到 SSH 会话进程退出时,它会被杀死。在这种情况下,有两种解决方案。一种是通过使用ssh.service
代替来避免使用套接字激活ssh.socket
。另一种是设置KillMode=process
在Service
一节ssh@.service
。
该KillMode=process
设置也可能对 classic 有用ssh.service
,因为它避免在服务器停止或重新启动时终止SSH 会话进程或screen或tmux进程。
这个答案显然获得了一定程度的普及。虽然它适用于 OP,但由于systemd-logind 开发或配置,它可能会在未来对某人不起作用。如果您遇到与此答案中的描述不同的行为,请查看有关 logind 会话的文档。
您是否将 systemd 与 SSH 的套接字激活一起使用?
如果是这样,则存在一个已知问题。根据 systemd 的支持者的说法,这实际上是一个功能——当会话终止时,systemd 会杀死会话产生的所有进程。(我可以看到这很有用,但是在 GNUscreen
或tmux
,情况下,您绝对不希望那样?当然,在用户可能运行后台进程的大多数其他情况下也是如此。)
如果是这样,请尝试从 切换sshd.socket
到sshd.service
。
小智 5
我在 Ubuntu 16.04 (kde neon) 上遇到了与 tmux 和 screen 相同的问题。当 ssh 会话断开时 screen / 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"