fix(terminal): 修复 PROMPT_COMMAND 钩子在子 shell 报「未找到命令」(#217) - #229
Merged
Merged
Conversation
bash 分支把 PROMPT_COMMAND 注册成裸函数名。PROMPT_COMMAND 是 shell 局部机制, 但它的值可能被环境导出并被后续 shell(su、tmux、exec bash、嵌套 ssh)继承, 而那些 shell 里没有本文件定义的函数,于是每个提示符都多输出一行 「bash: __onetcli_precmd_bash:未找到命令」,即 issue #217 的现象。 - 钩子改为自带存在性判断的命令串:`command -v` 是内建命令,函数缺失时静默跳过、 不产生 fork,也不受继承链路影响; - 退出码必须在钩子里先取好再显式传给函数:钩子里的 `command -v` 会覆盖 `$?`, 若仍让函数自己去读 `$?`,上报的 exit code 会恒为 0、`133;D` 失效; - 补两个回归测试:继承钩子但没有函数的 shell 必须静默、主 shell 退出码必须仍上报; - 设计文档记录该约束,避免以后被简化回裸函数名。 验证:`cargo test -p terminal`(503 lib 测试通过)、 `cargo clippy -p terminal --all-targets`(改动文件零告警);另在真实交互式 bash 中 对比复现:修复前子 shell 输出 2 行 command not found,修复后 0 行, 主 shell 的 `133;D` 退出码上报仍为 `false`→1、`true`→0。
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.
现象
部分服务器上执行命令时会额外输出一行
bash: __onetcli_precmd_bash:未找到命令(#217)。根因
crates/terminal/src/shell_integration.sh的 bash 分支把PROMPT_COMMAND注册成裸函数名__onetcli_precmd_bash。PROMPT_COMMAND是 shell 局部机制,但它的值可以被环境导出并被之后的 shell(su、tmux、exec bash、嵌套 ssh 等链路)继承。继承它的 shell 里并没有本文件定义的函数(函数不随环境走),于是 bash 在求值PROMPT_COMMAND时每个提示符都报一次「未找到命令」。同一个 shell 内不可能出现这种不一致(
PROMPT_COMMAND赋值在函数定义之后),所以报错必然来自继承了该变量的另一个 bash 进程;这也解释了为什么只有部分服务器复现。顺带排除一条看似相关的路径:
set -a(allexport)会把函数定义一起导出(BASH_FUNC_*),那种环境下子 shell 反而能拿到函数、不会报错——所以只有判断函数是否存在才是通用兜底,不能依赖某一种导出方式。修改
钩子改为自带存在性判断的命令串:
command -v是内建命令,不产生 fork;函数缺失时静默跳过。退出码改为在钩子里先取好再显式传给函数:钩子里的
command -v会覆盖$?,若仍让函数自己去读$?,上报的 exit code 会恒为 0、133;D失效。新增两个回归测试(先红后绿):继承钩子但没有函数的 shell 必须静默;主 shell 的退出码必须仍上报。
设计文档记录该约束,避免以后被简化回裸函数名。
验证
cargo test -p terminal:503 项 lib 测试通过cargo clippy -p terminal --all-targets:改动文件零告警export PROMPT_COMMAND场景):修复前子 shell 输出 2 行bash: __onetcli_precmd_bash: command not found,修复后 0 行false→133;D;1、true→133;D;0风险 / 后续
echo "$PROMPT_COMMAND"; type -t __onetcli_precmd_bash,可确认它的PROMPT_COMMAND是从哪条链路继承来的。Closes #217