feat: deploy 无密码时走密钥直连(收进 main,替代丢失的工作区补丁)

背景:2026-10-27 另一条线给 deploy.py 打的密钥补丁只放在
env-console 工作区未提交,切分支后丢失;部署一度只能靠它 +
--allow-dirty。本批把逻辑收进 main,并加一处加固。

分发:有 SSH_PASSWORD 时走 helper(pty 喂密码,实测最稳的一
路);无密码时 helper 不可用(会卡在密码提示),改走密钥直连:
ProxyCommand 显式环境变量优先、其次 helper 目录的
proxy_tunnel.py(存在才用),密钥按 CODEX_DEPLOY_KEY →
/root/.ssh/id_codex_deploy → ~/.ssh/id_codex_deploy 顺序显式传
-i——不能只依赖 /root/.ssh/config 的 Host 条目,那个目录会在
VM 回收时被清空(2026-10-27 05:04 实测),而 ~/.ssh 的那份
持久。两处都没有时不硬编造,靠 ssh 配置或 agent。

测试:deploy/tests 新增 TestSshScpCmd 5 个(有密码走 helper、
无密码绝不用 helper、无 helper 无代理时直连、显式代理优先、
显式密钥优先);全量 deploy 19、host 62、cloud 598 全过。
This commit is contained in:
host committed 2026-10-27 05:47:33 +08:00
1 parent 5ba4d35839
commit 420a7fecfd
2 files changed
+112 -8

No files matched your search

+45 -8
View File
@@ -156,30 +156,67 @@ def helper_path(name):
return path if os.path.isfile(path) else None
def ssh_cmd(host, user, remote_cmd):
"""返回一条 ssh 命令。优先用已验证稳定的 helper,否则用
SSH_PROXY_CMD 环境变量,否则直连。绝不把密码拼进命令。"""
helper = helper_path("ssh_run.py")
if helper:
return ["python3", helper, "ssh", host, user, remote_cmd]
def _deploy_key():
"""无密码时的部署密钥路径:显式环境变量优先,其次两处惯常
位置。/root/.ssh 的那份会在 VM 回收时被清空,~/.ssh 的那份
持久;两处都没有时返回 None(此时靠 ssh 配置或 agent,不
硬编造路径)。这里只返回路径,不读密钥内容。"""
env_key = os.environ.get("CODEX_DEPLOY_KEY")
if env_key:
return env_key
for cand in ("/root/.ssh/id_codex_deploy",
os.path.expanduser("~/.ssh/id_codex_deploy")):
if os.path.isfile(cand):
return cand
return None
def _proxy_cmd():
"""无密码时的 ProxyCommand:显式环境变量优先,其次 helper
目录的 proxy_tunnel.py(存在才用);都没有时返回 None(直
连,不把不存在的脚本写进命令)。"""
proxy = os.environ.get("SSH_PROXY_CMD")
if proxy:
return proxy
default_proxy = os.path.join(HELPER_DIR, "proxy_tunnel.py")
if os.path.isfile(default_proxy):
return "python3 %s %%h %%p" % default_proxy
return None
def ssh_cmd(host, user, remote_cmd):
"""返回一条 ssh 命令。有 SSH_PASSWORD 时优先用已验证稳定的
helper(pty 喂密码);无密码时走密钥直连:ProxyCommand 按
_proxy_cmd(),密钥按 _deploy_key() 显式传 -i(不能只依赖
/root/.ssh/config 的 Host 条目,那个目录会在 VM 回收时被
清空)。绝不把密码拼进命令。"""
helper = helper_path("ssh_run.py")
if helper and os.environ.get("SSH_PASSWORD"):
return ["python3", helper, "ssh", host, user, remote_cmd]
base = ["ssh", "-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null"]
proxy = _proxy_cmd()
if proxy:
base += ["-o", "ProxyCommand %s" % proxy]
key = _deploy_key()
if key:
base += ["-i", key]
return base + ["%s@%s" % (user, host), remote_cmd]
def scp_cmd(host, user, local, remote):
helper = helper_path("scp_run.py")
if helper:
if helper and os.environ.get("SSH_PASSWORD"):
# helper 自带 egress proxy + 密码 pty,是此前实测最稳的一路。
return ["python3", helper, "scp", host, user, local, remote]
proxy = os.environ.get("SSH_PROXY_CMD")
base = ["scp", "-o", "StrictHostKeyChecking=no",
"-o", "UserKnownHostsFile=/dev/null"]
proxy = _proxy_cmd()
if proxy:
base += ["-o", "ProxyCommand %s" % proxy]
key = _deploy_key()
if key:
base += ["-i", key]
return base + [local, "%s@%s:%s" % (user, host, remote)]