Skip to content

fix(ssh_execute): key-auth 主机启用守护进程 + Windows 下守护进程脱离作业对象存活 - #12

Open
pinewhite wants to merge 1 commit into
badseal:mainfrom
pinewhite:fix/windows-daemon-keyauth-survival
Open

fix(ssh_execute): key-auth 主机启用守护进程 + Windows 下守护进程脱离作业对象存活#12
pinewhite wants to merge 1 commit into
badseal:mainfrom
pinewhite:fix/windows-daemon-keyauth-survival

Conversation

@pinewhite

Copy link
Copy Markdown

Closes #11

English Summary

Fixes the per-call SSH handshake (~6s) on Windows for key-auth hosts: (1) enable the connection daemon for key auth, not only password auth; (2) make the auto-started daemon survive the AI tool's session job-object cleanup (CREATE_BREAKAWAY_FROM_JOB) and extend the startup wait from 3s to 20s so it covers the 6-8s cross-border handshake before the daemon info file is written. Measured: 6.0s → 0.68s per call, daemon alive across sessions. All 115 offline tests pass.

修复内容 / Changes(scripts/ssh_execute.py,+18/-11)

1. run_exec():密钥认证统一走守护进程

# before
has_password = params.get('password') is not None
use_daemon = has_password and not no_daemon

# after
loader.get_connection_params(alias)  # 保留:别名不存在时立即报错
use_daemon = not no_daemon

守护进程的 _connect_ssh() 本就完整支持密钥认证(RSA/Ed25519/ECDSA),没有理由只给密码认证用。保留 get_connection_params(alias) 调用以维持「别名不存在 → 立即报 config_not_found」的快速失败语义,不进入守护进程等待。

2. start_daemon_background():Windows 下脱离作业对象 + 等待窗口覆盖真实握手时间

  • CREATE_NO_WINDOWDETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_BREAKAWAY_FROM_JOB
    • AI 工具(Codex / Claude Code)命令会话结束按 Job Object 清理进程树;breakaway 让守护进程存活到下一次调用。已用探测进程实测:breakaway 子进程跨会话存活,普通子进程被连带回收。
    • 若 Job 不允许 breakaway,PopenOSError → 现有 except 安全降级直连,无回归。
  • 等待 10×0.3s40×0.5s:信息文件在 _connect_ssh() 完成后才写入,跨境握手 6-8s,原 3s 窗口必然超时。

macOS / Linux 分支(start_new_session=True)行为不变。

实测数据 / Measurements

Windows 11(10.0.26200),密钥认证主机,中国大陆 → 腾讯云跨境线路:

场景 修复前 修复后
ssh_execute <alias> "echo ok" 6.0s(每次全新连接) 0.68s(复用守护进程)
首次调用(自动拉起守护进程) 6.0s ~4.7s(一次性)
ssh_daemon.py status 永远 not_running running,跨命令会话存活,ssh_alive: true
远端非零退出码 正常 正常透传(exit 3exit_code: 3
长命令超时 正常 正常(守护进程侧 _execute_command 原逻辑不变)

测试 / Tests

python -m unittest discover -s tests
Ran 115 tests in 12.479s
OK

离线测试不覆盖真实跨会话存活场景(这正是 bug 逃过测试矩阵的原因),上面的实测数据来自真实环境验证。

…leanup on Windows

Two issues make every ssh_execute call pay a full SSH handshake (~6s on
cross-border links) instead of reusing the persistent daemon:

1. run_exec() only enabled the daemon for password auth
   (use_daemon = has_password and not no_daemon). Key-auth hosts always
   fell through to direct_execute, which spawns a fresh connection per
   call. Enable the daemon for both auth types.

2. start_daemon_background() on Windows used only CREATE_NO_WINDOW, so
   the daemon child belongs to the caller's job object and is killed
   when the AI tool session/process tree is cleaned up. It also waited
   only 3s while read_daemon_info() only appears after the SSH
   connection is established (6-8s on cross-border links), so the wait
   always expired and the next call started over.

Changes:
- run_exec: use_daemon = not no_daemon (keep get_connection_params for
  early config validation)
- start_daemon_background (Windows): DETACHED_PROCESS |
  CREATE_NEW_PROCESS_GROUP | CREATE_BREAKAWAY_FROM_JOB so the daemon
  escapes the caller's job object; extend wait to 40x0.5s

Measured on Windows 11 (key-auth host, China -> Tencent Cloud):
- before: ~6.0s per echo, new connection every call
- after first call (~4.7s, daemon boot): ~0.68s per echo, daemon reused
  across sessions (ssh_daemon.py status: running, ssh_alive=true)

All 115 offline tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows + 密钥认证主机:每次调用都重新 SSH 握手(守护进程从未生效),握手 ~6s/次

1 participant