如何通过CircleCI连接私有EC2实例并解决SSH部署报错?
问题解决:CircleCI通过跳板机连接私有EC2实例失败
核心问题
你的部署脚本存在引号语法错误,导致第二个ssh命令将私有实例IP和后续的部署命令拼接成了一个完整的主机名字符串,ssh尝试解析这个混合字符串时自然会失败——错误信息里的10.0.20.108 cd /var/www/...就是明证,它把整个内容当成了要连接的主机名。
修正后的部署脚本
以下是修复后的aws_deploy.sh脚本,采用更清晰的here-doc语法避免引号混乱,同时确保命令正确嵌套执行:
#!/bin/bash BRANCH=$1 JUMP_SERVER=$2 PRIVATE_SERVER=$3 # 通过跳板机连接私有实例并执行部署流程 ssh -A -tt -o StrictHostKeyChecking=no $JUMP_SERVER << EOF ssh -i sultan-key.pem -o StrictHostKeyChecking=no $PRIVATE_SERVER << INNER_EOF cd /var/www/linkedunion-development/ git fetch --all git checkout -B $BRANCH origin/$BRANCH docker-compose down -v docker system prune --all --force docker stop \$(docker ps -q) docker rm \$(docker ps -aq) docker rmi \$(docker images -q) git pull ./git_fetch.sh INNER_EOF EOF
关键修复点
- 移除多余引号:原脚本中第一个
ssh命令结尾的\"是多余的,直接导致语法解析混乱。 - 使用嵌套here-doc:通过
<< EOF和<< INNER_EOF结构,清晰分隔跳板机和私有实例的执行命令,彻底避免引号转义错误。 - 统一变量传递:将参数赋值给明确的变量(
BRANCH、JUMP_SERVER等),提升脚本可读性和维护性。 - 全链路禁用主机检查:在私有实例的ssh命令中也加入
StrictHostKeyChecking=no,避免CI环境中首次连接的交互式确认问题。
额外注意事项
- 确保跳板机上的
sultan-key.pem路径正确,且拥有可读权限(可执行chmod 600 sultan-key.pem确保权限合规)。 - 如果你使用了SSH Agent Forwarding(
-A参数),可以考虑去掉私有实例ssh命令中的-i sultan-key.pem,直接通过转发的密钥认证,减少文件依赖。 - 验证私有实例的IP在跳板机上是否可连通(可在跳板机上手动执行
ping $PRIVATE_SERVER确认)。
内容的提问来源于stack exchange,提问作者Sultan Muhammad
相关产品推荐
相关产品推荐

