正如问题所述,我正在尝试更好地理解会话、进程、进程组等。这是我在使用 tmux 时遇到的一些问题。
如果我打开 tmux 并运行 ps,我会看到两个 bash 进程。如果我理解正确的话,第一个bash进程对应于父shell,第二个bash进程是tmux打开的进程?
如果我使用
kill
tmux 进程,终端似乎会返回到父 shell,但如果我再次运行 ps,我会看到两个 bash 进程。我的猜测是,第二个 bash 进程是 tmux 打开的进程,但我不再在该终端上连接到该进程?在进程组和会话方面,第二个 bash 进程与第一个 bash 进程有何关系?我如何
kill
执行第二个 bash 过程?用PID运行kill
似乎没有任何作用。还有一种方法可以将我的终端从一个外壳中分离出来并切换到另一个外壳吗?如果我打开
Ctrl+D
tmux,tmux 和第二个 bash 进程都会正常退出。这是因为 tmux 在 tmux 关闭之前发送了一个结束 bash 进程的信号吗?为什么这比kill
.
我在 macOS 终端上从 bash shell 运行 tmux。我从 shell 中输入 tmux 来运行它。一旦 tmux 在终端中打开,我就运行 ps。当我获得 tmux 的 pid 时,我运行kill [pid],然后再次运行 ps 。我从未配置过 tmux,所以我想 .tmuxrc 文件仍将保持默认状态。
答案1
第 1 步:运行 tmux
最初,您打开一个终端,并在其中运行 bash。我将其称为原始 bash。
你tmux
从原来的bash中跑了出来。 Tmux 运行两个进程:tmux 服务器和 tmux 客户端。它这样做的原因是您可以从 tmux 会话中分离并稍后重新附加到它 - 这是 tmux 的核心功能。 tmux 客户端连接到附加会话的终端。服务器运行在 tmux 窗口中运行的进程。当您从会话中分离 ( C-b d
) 时,客户端将退出,但服务器和会话中运行的进程将继续运行。除了两个 tmux 进程之外,假设您尚未启动 tmux 会话,tmux
则会创建一个新会话,其中包含一个运行 shell 的窗口:这是第二个 bash。
此时,流程树的相关部分如下所示:
…
├─tmux: server───bash───pstree
└─xterm───bash───tmux: client
这是来自pstree
Linux 上的命令。要在 macOS 上获得类似的显示,请参阅https://apple.stackexchange.com/questions/11770/linux-ps-f-tree-view-equivalent-on-osx。xterm
是我运行原始 bash 的终端,并且是通过在原始 bash 中tmux: client
运行而启动的 tmux 客户端。是 tmux 客户端启动的 tmux 服务器,它的子级是我运行的第二个 bash 。tmux
tmux: server
bash
pstree
ps
在 Linux 上,这是内部 tmux的输出:
PID TTY TIME CMD
108 pts/56 00:00:00 bash
153 pts/56 00:00:00 ps
默认情况下,Linuxps
仅显示当前终端上运行的进程。这就是我所看到的原因。在 FreeBSD 上,我希望也在 macOS 上(我在 shell 是 zsh 的机器上运行这个,这就是为什么它显示 zsh 而不是 bash):
19690 0 Is 0:00.36 /usr/local/bin/zsh
20046 0 I+ 0:00.01 tmux: client (/tmp//tmux-1001/default) (tmux)
20049 1 Rs 0:00.06 /usr/local/bin/zsh
20138 1 R+ 0:00.01 ps
BSDps
显示更多进程的原因是,默认情况下,它显示附加到任何终端的进程。 (技术术语是“具有控制终端”的进程。)它不显示根本不附加到终端的进程,例如 tmux 服务器。
要查看涉及的所有进程并获取有关这些进程的更多信息,让我们ps
使用几个选项来运行。在不同的 UNIX 变体上,查看相关数据的选项略有不同。我将展示 Linux 和 FreeBSD; macOS 可能与 FreeBSD 很接近,但可能略有不同。在 Linux 上,以下是ps x -o pid,ppid,tty,comm f
过滤到相关进程的 的输出:
PID PPID TT COMMAND
107 1 ? tmux: server
108 107 pts/1 \_ bash
154 108 pts/1 \_ ps
3 1 ? xterm
6 3 pts/0 \_ bash
105 6 pts/0 \_ tmux: client
在 FreeBSD 上,ps -U $(id -u) -A -o pid,ppid,tty,command -d
(在 macOS 上,您需要删除-d
,并且不会获得树演示)(再次过滤;在 FreeBSD 上,我远程登录,因此原始 zsh 位于由 提供的终端中sshd
):
PID PPID TTY COMMAND
19689 19687 - sshd: gilles@pts/0 (sshd)
19690 19689 pts/0 - /usr/local/bin/zsh
20046 19690 pts/0 `-- tmux: client (/tmp//tmux-1001/default) (tmux)
20048 1 - tmux: server (/tmp//tmux-1001/default) (tmux)
20049 20048 pts/1 - /usr/local/bin/zsh
20149 20049 pts/1 `-- ps -U 1001 -A -o pid,ppid,tty,command -d
在这两种情况下,您都可以看到六个进程:
- 提供的终端仿真器
pts/0
。 - 原始 shell,运行在
pts/0
. - tmux 客户端在 中运行
pts/0
,从原始 shell 启动。 - tmux 服务器。它不在终端中运行。它的父进程 (
PPID
) 是进程 1。(发生这种情况是因为当 tmux 客户端启动服务器时,它会进行双重分叉:它创建一个子进程,该子进程本身创建子进程,然后立即退出。当中间进程退出时,孙子进程将成为孤儿进程因此被采用在里面,即过程 1。) - 在 tmux 内运行的 shell。它在单个 tmux 窗口(即终端)内运行
pts/1
。 ps
在 tmux 内的 shell 内运行。
第2步:杀死tmux
你杀死 tmux 进程。但哪一个呢?我们在上面看到有两个。我们还在上面看到,在 macOS 上,ps
没有选项显示终端中运行的所有进程。所以你看到并杀死了 tmux 客户端。这相当于从会话中分离。 tmux 服务器仍在运行。这是使用 tmux 的原因之一:如果客户端被终止,例如因为运行客户端的终端消失,会话将继续运行。
第 3 步:重新连接会话
您可以使用 来查看现有的 tmux 会话tmux list-sessions
。您可以使用 重新连接到它tmux attach
。如果您有多个会话,您可以通过在 后面传递会话编号来选择要附加到哪个会话tmux attach
,例如tmux attach 0
附加到tmux list-sessions
描述为 的会话0: 1 windows (created …) …
。
如果您想终止会话而不附加它,您可以使用tmux kill-session
。甚至有一个命令tmux kill-server
可以终止所有会话。
第四步:正常退出
当您按 Ctrl+D 或在 tmux 内的 shell 中输入时exit
,shell 将退出。当 tmux 窗口的主进程退出时,tmux 会关闭该窗口。当 tmux 关闭最后一个窗口时,会话退出。
答案2
我正在使用默认设置运行 Fedora 32。
如果我打开 tmux 并运行 ps,我会看到两个 bash 进程。
tmux 本身是 bash 的子级,但是它需要为您提供一个独立的 shell(这就是应用程序的全部要点 - 能够分离会话),因此它会生成另一个 bash 实例。
如果我终止 tmux 进程,终端似乎会返回到父 shell,但如果我再次运行 ps,我会看到两个 bash 进程
这取决于你如何杀死它。
tmux 生成它自己的子进程,然后该子进程生成一个 shell。
如果您杀死子 tmux,则子 bash 应该终止,并且您将留下一个 bash 进程。
如果您杀死父 tmux,子 tmux 将继续运行其下的 bash 进程,即您将获得两个 bash 进程。
答案3
在理解会话方面,环境tmux
有点特殊,主要是因为它的设计就是如此。通常,当您终止一个进程时,它的所有子进程都会被系统收获(终止)。 (这极大地简化了实际发生的情况,并且只有在特定上下文中才能获得最终结果,才能真正被认为是准确的。)
有了tmux
,这种安排就被改变了。tmux
旨在让您启动 shell,然后从该会话断开连接以注销并稍后重新登录并重新连接到同一会话。因此,尽管它的父母被杀,它还是让它的孩子活着。
具体就您的情况而言,您从一个流程开始,即bash
流程。那是你当前的外壳。当您调用 时tmux
,当前 shell 会启动一个名为 的子级tmux
,并tmux
自动启动其自身的子级bash
。这一秒bash
是您运行ps
命令的地方。当您终止原始 shell 时tmux
,您实际上并没有终止会话tmux
,只是终止了与它的连接。因此,您的孙子 shell 在tmux
会话中保持运行,并且您将转储回父 shell。
请参阅tmux
手册页,了解如何连接到现有tmux
会话或断开连接,以及如何更有效地使用tmux
.