Replies: 1 comment
|
你好,我完整复现并验证了你报告的问题:交互式 bash 的历史展开发生在解析之前,其引号扫描不认识 |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
环境
@deepseek-ai/dsh0.1.0-rc.7(dsh-tool-bash-persistent同版本)/bin/bash3.2bash工具,即@deepseek-ai/dsh-tool-bash-persistent)现象
在持久 bash 中执行任意带单引号参数、且参数内容含
!的命令:echo 'hello!world'→ 报bash: !world'': event not found,命令完全不执行MYSQL_PWD='xx#yy!zz' mysql -h127.0.0.1 -uroot db -e "SELECT 1;" 2>&1 | head -60→ macOS 上表现为Your command timed out after 300 seconds,部分输出只有一行dsh>提示符,mysql 从未被执行bash -c)下秒回、结果正常最小复现(无需任何真实密码)
在持久 bash 工具内执行:
hello!worldbash: !world'': event not found,无任何输出echo "hello!world"(双引号)→ 正常输出hello!worldecho 'no-bang'→ 正常输出no-bang根因分析
dsh-tool-bash-persistent/lib/index.js的wrapCommand/quoteForBash)把每条命令包装成:printf '%s\n' $'START'; eval -- $'<command>'; ...; printf '%s%s\n' $'END:' "$status"其中命令里的单引号被转义成
\'放进外层$'...'。bash --noprofile --norc -i,跑在 PTY 上),默认开启set -H(历史展开)。$'...'内部的\'转义:$'打开引号区后,遇到第一个\'里的'就误判为引号区结束,于是!world、!zz暴露在引号区之外,触发 history expansion →event not found→ 整行被拒绝执行、零输出(START/END 标记都不会出现)。stdin_read/ shell 退出 / 自身 300s 截止。行被拒后 END 标记永远不会出现。dsh-subprocess-local的MacProcessInspector.isStdinWaiting()硬编码返回false(150ms 快速stdin_read结算永不触发),且ps -o tpgid=的前台进程组检测在 PTY 场景下不可靠,因此后端只能反复走 3.5s 的inferred_idle结算,工具空转到 300s 才报超时。(Linux 上isStdinWaiting正常,可能表现为快速返回event not found而非超时——但命令同样是失败的。)建议修复(按优先级)
stty -echo后追加set +H(一处小改动;已实测:set +H后原命令正常执行并返回结果)。quoteForBash中把!转义为\!(治标:$'...'内的!本就不该被展开,历史展开的引号跟踪才是问题本体)。临时 workaround(已实测验证)
MYSQL_PWD="xx#yy!zz"→ 正常(注意双引号内$、反引号、\会被 shell 展开,需按需处理)set +H(持久 shell 状态保持,后续命令均正常)MYSQL_PWD='xx#yy'\!'zz'→ 正常影响面
任何在持久 bash 中执行、且 wrapped 形式会在
$'...'外暴露!的命令(单引号参数含!的密码、URL、字符串字面量等)。交互式 bash 默认set -H,这是所有平台的共性问题;macOS 因结算路径缺陷放大为 300s 超时。All reactions