fix(daemon): 修复 PM2 God 的 systemd cgroup 归属 - #919
Open
emosheeep wants to merge 1 commit into
Open
Conversation
emosheeep
marked this pull request as ready for review
August 18, 2026 14:02
Owner
|
这是一条自动化初步评审意见,最终以维护者审阅为准。 整体看, 有几项非阻断的升级体验建议:
以上不否定核心生命周期方案,主要是让受 #774 影响最直接的存量安装在升级时有清楚、安全的出路。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
Closes #774
PM2 God 首次启动时会继承调用方所在的 cgroup;即使随后 daemonize,也不会自动迁出该进程组。因此,如果首次启动来自 IDE、Agent Runner 或其他 systemd service,PM2 God 和 Botmux daemon 的生命周期会意外绑定到该调用方,调用方重启或清理 cgroup 时会连带终止 Botmux。
本 PR 将 Linux 下的生命周期明确为:
修改思路
1. 让 systemd 正式接管 PM2 God
Linux user service 从
Type=oneshot + RemainAfterExit调整为:Type=forkingPIDFile=~/.botmux/pm2/pm2.pidMainPID指向 PM2 GodExecStart、ExecStop使用仅限 systemd service 内部调用的入口PM2 God 由
botmux.service内部创建,因此 God、daemon 和 dashboard 都进入独立的botmux.servicecgroup,不再继承执行botmux start的终端或其他 supervisor。Service 使用
KillMode=process,并由经过 PID、进程启动代际和 cgroup 校验的ExecStop精确结束 PM2 God,避免 systemd 在重启时误杀需要跨 daemon 重启保留的 tmux、herd 或 zellij 会话。2. 普通 restart 自动修复已有 Service
botmux restart在 Linux 下会:~/.config/systemd/user/botmux.servicesystemctl --user daemon-reloadbotmux.service的 MainPIDsystemctl --user restart botmux.service完成迁移已有的旧版
Type=oneshotunit 不需要手动删除或重新执行autostart enable,普通 restart 即可修复文件和运行态。实现只维护一个主
botmux.service,不生成额外的 drop-in/conf 文件。3. 拒绝复用其他 supervisor 的 God
新增 Linux PM2 lifecycle ownership 检查,通过
/proc同时绑定 PM2_HOME、PID、进程启动代际和 systemd cgroup。当已有 God 属于其他 service/cgroup 时,start、restart、插件服务 mutation 和 autostart 操作都会 fail closed,并提示先从原 owner 迁出。本 PR 不会自动结束外部 God,避免越权操作其他 supervisor 管理的进程。
4. 只读命令不隐式拉起 PM2
PM2 的公共 CLI/connect 路径在 socket 不存在时可能自动创建 God。新增只读 RPC 客户端用于 status、logs 和 Desktop 查询:
5. 约束已有 God 上的 mutation
插件服务等必须修改现有 PM2 registry 的操作会在 mutation 前确认 God 唯一且属于
botmux.service,关闭 RPC socket 自动重连,并在发送请求前再次校验 PID、启动代际和 cgroup。God 消失或被替换时直接失败,不在调用方 cgroup 中创建新 God。6. 保留插件服务与持久会话
影响范围
设计边界
本 PR 聚焦 Issue 要求的基本生命周期问题:建立明确的
botmux.serviceowner、校验并拒绝外部 God、自动修复旧版主 Service、阻止只读命令隐式 daemonize。没有引入额外 drop-in 配置、持久迁移 journal 或跨崩溃恢复事务。
验证
构建
通过,包括 TypeScript 编译、dashboard bundle 和 dist audit。
定向测试与真实 systemd E2E
pnpm exec vitest run \ test/autostart-existing-unit-repair.test.ts \ test/autostart-pm2-ownership.test.ts \ test/autostart-refresh-retry.test.ts \ test/plugin-service-manual-snapshot.test.ts \ test/pm2-existing-client.test.ts \ test/pm2-readonly-cli.test.ts \ test/desktop/desktop-pm2-apps.test.ts \ test/plugin-pm2-env.test.ts \ test/shutdown-supervisor-contract.test.ts \ test/systemd-pm2-migration.e2e.ts结果:10 个测试文件、62 个用例全部通过。
真实 systemd E2E 覆盖:
Type=oneshotunit 迁移到Type=forking本地运行
实际读回:
botmux.service为active/runningType=forkingMainPID与唯一 PM2 God PID 一致botmux-0、dashboard 均属于botmux.servicecgrouponline