如何在BATS测试的Bash函数中激活ssh-account且不导致测试挂起?
问题根因
你手动执行脚本时,ssh-agent作为后台守护进程留存不会影响终端返回,但BATS测试默认会等待所有测试过程中派生的子进程终止才会标记测试完成,长期运行的ssh-agent进程、或者ssh-add触发密钥密码交互提示都会导致测试无限挂起。
解决方案
方案1:复用现有ssh-agent,测试结束统一销毁(优先推荐)
修改activate_ssh_account函数,避免重复启动ssh-agent,同时在BATS测试层统一管控agent生命周期:
- 函数内增加存活agent检测逻辑,避免重复生成新的agent进程
activate_ssh_account() { local git_username=$1 # 仅当无存活ssh-agent时才启动新实例 if [ -z "$SSH_AGENT_PID" ] || ! kill -0 "$SSH_AGENT_PID" 2>/dev/null; then eval "$(ssh-agent -s)" >/dev/null fi # 替换为你实际的密钥路径规则 ssh-add "$HOME/.ssh/${git_username}_id_rsa" }
- 在BATS测试文件中增加初始化和自动清理逻辑
# 测试前置钩子,每个测试文件运行前执行一次 setup_file() { eval "$(ssh-agent -s)" >/dev/null # 测试全部跑完自动销毁agent进程 trap 'kill $SSH_AGENT_PID' EXIT }
方案2:关闭ssh-add的交互逻辑,避免密码输入阻塞
如果你的SSH密钥设置了密码,ssh-add在非交互环境下会静默等待密码输入导致挂起,可做以下调整:
- 测试环境使用无密码的专属测试密钥,避免密码校验
- 给ssh-add增加输入重定向,遇到交互场景直接退出:
ssh-add 你的密钥路径 < /dev/null
方案3:限制ssh-agent生命周期在函数范围内
如果activate_ssh_account不需要把ssh-agent留给后续命令使用,仅需要单次执行加密钥操作,可以在函数内绑定agent销毁钩子:
activate_ssh_account() { local git_username=$1 eval "$(ssh-agent -s)" >/dev/null # 函数退出时自动销毁当前agent trap 'kill $SSH_AGENT_PID' RETURN ssh-add "$HOME/.ssh/${git_username}_id_rsa" # 此处写需要用到SSH密钥的业务逻辑,执行完agent会自动清理 }
内容的提问来源于stack exchange,提问作者a.t.
相关产品推荐
相关产品推荐

