关闭Muxy后终端还在跑:深度解析Muxy背景会话(Background Sessions)功能
【免费下载链接】muxyLightweight and Memory efficient terminal for Mac built with SwiftUI and libghostty项目地址: https://gitcode.com/gh_mirrors/muxy1/muxy
还在担心关掉 Muxy 窗口,里面跑的npm run dev或长时间构建任务就会中断吗?Muxy 是一款用 SwiftUI 和 libghostty 构建的轻量级、低内存占用的 Mac 终端,它的**背景会话(Background Sessions)**功能正是为解决这个问题而生:开启后,即使你彻底退出 Muxy,终端里运行的进程也会继续在后台存活,重新打开 Muxy 时还能"接回"原来的会话——就像 tmux 一样,但完全内置、无需额外配置。
什么是 Muxy 背景会话?一句话理解原理
背景会话 = 每个终端跑在一个独立于 App 的守护进程里,关掉 Muxy 只断开"显示器",不杀"程序"。
由于 libghostty 独占每个终端表面的 PTY,无法把一个已有的终端"移交"给外部进程,所以 Muxy 采用了和 tmux 相同的拆分思路:
- 一个名为
muxy-session的守护进程持有每个后台会话的真实 PTY,并通过setsid运行在自己的会话中,从而在 App 退出后依然存活; - 每个终端面板实际运行的是
muxy-session attach—— 一个轻量客户端,通过 Unix socket 代理字节流、窗口尺寸和最终的退出状态。
退出 Muxy 时,被杀掉的只是这些 attach 客户端,守护进程和它管理的 shell 继续运行。相关实现可以参考 MuxySession/main.swift 与 MuxySession/SessionDaemon.swift。
一键开启:如何启用 Background Sessions 设置
开启路径非常简单:
👉Settings → Terminal → Background sessions
几个新手需要知道的细节:
- 默认关闭:偏好项默认值为
false(见 TerminalPersistentSessionPreferences.swift),不会悄悄改变你的终端行为; - 只影响新开的终端:开关打开后,只有之后新建的终端才走后台会话,已经打开的终端保持原行为;
- 仅限本地终端:远程 SSH 面板和 Quick Terminal(快速终端)永远不会使用后台会话(策略见 TerminalPersistentSessionPolicy.swift)。
关闭Muxy后,会话是怎么"复活"的?
这是背景会话最妙的部分,分为三个环节:
1. 会话 ID 随工作区持久化
每个面板都带一个会话 ID(默认为其面板 ID),并随工作区快照一起持久化。重新打开 Muxy 时,恢复的面板会自动重新连接回它自己的会话。
2. 256 KB 输出回放 + 自动重绘
重连时,守护进程会回放最近256 KB的普通输出缓冲(实现见 MuxySessionProtocol/SessionReplayBuffer.swift),并向前台进程组发送SIGWINCH,让vim、htop这类全屏程序立刻重绘画面。回放内容是"净化"过的:不完整的 UTF-8 序列和终端控制序列会被丢弃,而不是原样发给新界面。
3. 自动重连,绝不丢失工作
- attach 客户端会在守护进程空闲关闭的瞬间按需拉起它,并持续重试"连接 + 启动"整个循环,直到成功或预算耗尽——所以你在旧守护进程退出过程中打开终端也不会失败;
- 重连后 Muxy 会先向守护进程确认会话状态:只有守护进程确认会话真的结束了才会关闭标签页;守护进程不可达会被当作"连接掉线"处理,带退避地重连;
- 连续多次失败时,标签页会停留在Reconnect占位界面上,会话本身继续运行——守护进程崩溃或版本升级都不会帮你"顺手"关掉标签。
Send to Background:把标签页安全"丢进后台"
即使 Muxy 没退出,你有时也想腾出标签页但保留进程。操作方式:
- 在终端里右键点击;
- 选择Send to Background。
标签页会关闭,但里面的进程继续运行,会话随即以detached(已脱离)状态出现在状态栏中。注意几个限制:固定(pinned)标签页、混合内容分屏、远程终端、以及未开启背景会话的终端都不支持此操作。
在状态栏找回脱离会话:接管、新建、停止
状态栏只会列出当前项目和工作区中、没有任何标签页占用的会话——已经打开在标签里的会话不需要你恢复,所以不会重复出现。每一条记录都展示会话标题和工作目录,并提供三个操作:
| 操作 | 作用 |
|---|---|
| Active tab | 让当前聚焦的标签页接管该会话(原会话转为脱离状态,占据空位) |
| New tab | 在当前工作区新建一个标签页并附着到该会话 |
| Stop | 结束该会话及其内部所有进程 |
一个会话同一时刻只能被一个标签页占用:当你接管某个会话时,它原来的主人会自动分到一个全新的会话,不会出现"死终端"。详细文档可阅读 docs/features/terminal.md。
CLI 管理后台会话:不打开 App 也能控制
安装 Muxy CLI 后(菜单Muxy → Install CLI),你可以在任意 shell 中管理后台会话:
# 列出所有后台会话(会话ID、shell PID、工作目录、是否附着、标题……) muxy list-sessions # 结束指定会话及其内部所有进程 muxy kill-session --session "$SESSION"输出的attached列取true表示有终端面板正连着该会话,false表示它在无人看管地运行。更多用法见 docs/features/muxy-cli.md。
安全设计:普通用户动不了你的会话
- 控制 socket 放在 Muxy 的 Application Support 目录,目录权限
0700、socket 权限0600;仅当主路径超过 Unix 104 字节sun_path限制时,才回退到用户级的/tmp/muxy-<uid>; - 守护进程通过
LOCAL_PEERCRED校验连接方的 uid,拒绝其他用户的连接; - 开发版使用独立的
sessions-dev目录,与正式版互不干扰(实现见 PersistentSessionPaths.swift)。
此外,守护进程会手动复现 Ghostty 的 shell 集成注入(zsh 用ZDOTDIR、bash 用ENV、fish/elvish/nushell 用XDG_DATA_DIRS),因此后台终端依然拥有工作目录追踪、标签标题、提示符标记和 AI 进度显示;zsh/bash/fish 之外的 shell 则与 tmux 下表现一致,仅失去这些集成。
常见问题 FAQ
Q1:我为什么感觉功能没生效?先确认开关已打开、并且是开关打开之后新建的终端;远程终端与 Quick Terminal 本身就不走后台会话。
Q2:守护进程会不会一直占着内存?不会。守护进程在空闲且没有任何会话时会自动退出;下次 attach 客户端会按需重新拉起它。
Q3:重连时看到的画面是"录像回放"吗?是的,且是尽力而为的:只回放最近 256 KB 的普通输出并做净化处理;全屏程序(如 tmux 内部、vim)跳过原始回放,依赖SIGWINCH触发的重绘。
Q4:Muxy 升级后旧会话还能接管吗?每次 attach 都携带协议版本号,不同版本 Muxy 启动的会话会被明确拒绝并给出清晰提示,而不是被"误读",避免损坏你的工作现场。
小结
Muxy 的背景会话功能用不到十秒的开关成本,换来的是 tmux 级别的进程存活能力:守护进程持有 PTY、256 KB 净化回放、自动重连与状态确认、状态栏脱离会话管理,再加上muxy list-sessions/kill-session的 CLI 控制——长任务不再需要"手抖不敢关 App",这正是 Muxy 作为一款现代 Mac 终端的底气所在。🚀
【免费下载链接】muxyLightweight and Memory efficient terminal for Mac built with SwiftUI and libghostty项目地址: https://gitcode.com/gh_mirrors/muxy1/muxy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考