feat(backend): 兼容 rcfile exec 切换 shell 导致会话起不来的场景#314
Merged
Conversation
|
To use Codex here, create a Codex account and connect to github. |
修复用户登录 $SHELL(如 bash)的 rc 文件里有 `exec zsh` 之类跳转时, botmux 用 `<$SHELL> -i -c '… exec /usr/bin/env <cli>'` 在 tmux pane 里 启动 CLI——`-i` 会 source `.bashrc`,`exec zsh` 在 `-c` body 跑到之前 就把 shell 顶替掉,CLI 的启动命令永远没机会执行,pane 沦为裸 zsh, 首条多行 prompt 被打进去报 `zsh: parse error near '\n'`,会话假死。 两层修复(不动现有 wrapper 启动形态,零回归面): - L2 裸壳检测安全网:打首条 prompt 前,比对 pane leaf 进程 comm 是否为 裸壳(bash/zsh/sh/…)。是则不把多行 prompt 打进去,改发一张飞书诊断 卡片,点名最可能的 rc trampoline 根因 + 两种修法。检测点选在 flushPending 首刷处——首条 prompt 本就被 hold 到 ready 或 15s/45s 超时,届时健康 CLI 早已 exec,只有 trampoline/启动失败才仍是裸壳,误报率极低。跳过 wrapperCli(launcher 合法套壳)/ adopt(观察既有 pane)。把「排查一晚上」 压成卡片上一眼可见的根因。 - L3 per-bot launchShell 覆盖:新增 BotConfig.launchShell,指定启动 CLI 用的 shell(zsh|bash|sh 或绝对路径),覆盖 $SHELL,直接绕开会跳转的 rc。 贯通 init payload → SpawnOpts → resolveUserShell(env, override)(tmux-pipe / zellij / 旧 tmux backend 三处 call site)。两套配置面:/config launchShell + dashboard「机器人默认设置 → 启动 Shell」,写盘走统一 applyConfigField。 测试:resolveShellOverride / resolveUserShell 覆盖 5 例、isBareShellComm 4 例; 真实 tmux pane 端到端验证:bug 变体落裸 zsh、launchShell=zsh 变体正常拉起 CLI。 全量单测 375 文件 6374 例通过。文档:bots-json 表加 launchShell(中英)。
Codex review 指出:原注释称 reattach 跳过裸壳检测,但实现只重置 bareShellLaunchBlocked,检测实际靠 !hasRunStartupCommands 间接 gate。 而 reattach 时 hasRunStartupCommands=true → 检测被跳过,若 daemon 重启 复用到一个已退化成裸壳的持久 pane,首条消息会被直接打进 shell(正是本 PR 要消除的 bug)。 改为独立一次性 gate bareShellChecked:检测在每个 spawn(含 reattach)的 首刷只跑一次,仅当 leaf 确为裸壳才触发——健康 reattach(leaf=存活 CLI) 自动不命中,退化 pane 则正确弹诊断卡而非打进 shell。注释同步纠正。 另把诊断分档抽成纯函数 bareShellLaunchKind(leafComm, expectedShell) (session-discovery.ts)并补 3 个单测,回应 Codex「补个小测试」建议。 全量单测 375 文件 / 6377 例通过。
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.
背景
用户(江威峰)配置 botmux + Codex 后会话起不来:首条多行 prompt 落进裸
zsh报zsh: parse error near '\n',手敲codex才能 work。根因:用户
$SHELL=/bin/bash,但~/.bashrc里有[ -t 1 ] && exec zsh(chsh 失败的 hack)。botmux 在 tmux pane 用<$SHELL> -i -c '… exec /usr/bin/env <cli>'启动 CLI(tmux-pipe-backend.ts:createDetachedSession)——-i会 source.bashrc,pane stdout 是 tty →exec zsh在-cbody 跑到之前就顶替 bash,CLI 的启动命令永远没机会执行,pane 沦为裸 zsh。经分析对四种方案做了对抗性压测(含真机验证)。关键约束:tmux
new-session的 pane 不继承 client env,只继承 server 全局 env——所以"抓 rc env 再塞回去"的透明兼容(L1)雷区最多,本 PR 按申晗决定跳过 L1,落 L2 + L3。改动
L2 · 裸壳检测安全网(
worker.ts+session-discovery.ts)打首条 prompt 前,比对 pane leaf 进程
comm是否为裸壳(bash/zsh/sh/dash/ash/…)。是则不把多行 prompt 打进去,改发一张飞书诊断卡片,按$SHELLvs leaf 是否一致分两档点名根因(trampoline / 启动慢·CLI 没找到)+ 修法。flushPending首刷处:首条 prompt 本就被 hold 到 ready 或 15s/45s 超时,届时健康 CLI 早已 exec,只有 trampoline/失败才仍是裸壳 → 误报率极低。wrapperCli(launcher 合法套壳)/adoptMode(观察既有 pane);pty/herdr 直接 exec CLI,leaf 永不是裸壳,天然不触发。runStartupCommands之前跑(否则 startupCommands 会先被打进裸壳)。L3 · per-bot
launchShell覆盖新增
BotConfig.launchShell(shell 名或绝对路径),覆盖$SHELL启动 CLI,直接绕开会跳转的 rc。init payload → SpawnOpts → resolveUserShell(env, override),三处 call site(tmux-pipe / zellij / 旧 tmux backend)。/config launchShell(CONFIG_FIELDS)+ dashboard「机器人默认设置 → 启动 Shell」,写盘统一走applyConfigField。验证
resolveShellOverride+resolveUserShelloverride 5 例、isBareShellComm4 例。.bashrc=[ -t 1 ] && exec zsh的 fake HOME(-e HOME注入 pane env)——bash -i):pane leaf=zsh、fakecli 未启动 ✓ 复现zsh -l -i,launchShell=zsh):fakecli 正常拉起 ✓bots-json.md配置表加launchShell(中英同步)。Review 关注点(供 @codex)