如何通过SSH从Jenkins Worker节点在远程主机执行多条命令?
Jenkins声明式流水线通过SSH执行远程多命令方案
问题场景
需要在Jenkins声明式流水线的部署阶段,从指定Worker节点通过SSH连接Docker宿主机,顺序执行以下部署命令:
cd myDirectory docker stack deploy --compose-file docker-compose.yml foo
当前已实现单条SSH命令执行,但多命令执行配置运行失败,错误配置如下:
pipeline { agent { label 'onlyMyHost' } stages { stage("checkout"){...} stage("build"){...} stage("deploy") { steps { sshagent(credentials: ['my-sshKey']){ sh 'ssh -o StrictHostKeyChecking=no myUser@foo.bar.com hostname' sh (""" ssh -o StrictHostKeyChecking=no myUser@foo.bar.com 'bash -s' < "cd MyDirectory && docker stack deploy --composefile docker-compose.yml foo" """) } } } } }
失败根因
bash -s用法错误:bash -s从标准输入读取待执行脚本,当前写法中<后接的是命令字符串而非本地脚本文件路径,SSH无法获取到要执行的完整内容- 命令存在拼写错误:docker stack deploy的参数为
--compose-file,配置中误写为--composefile;目标目录名大小写不匹配(原目录为myDirectory,配置中写为MyDirectory) - 引号嵌套逻辑错误:双引号包裹的命令内容会被本地shell提前解析,无法完整传递到远程主机执行
可行实现方案
方案1:单行拼接多命令(适合短命令场景,配置最简单)
SSH原生支持在连接参数后直接携带远程执行命令,多条命令用&&拼接即可,无需额外调用bash -s,注意统一使用外层双引号包裹远程命令、路径写绝对路径避免工作目录不确定问题:
stage("deploy") { steps { sshagent(credentials: ['my-sshKey']){ sh 'ssh -o StrictHostKeyChecking=no myUser@foo.bar.com "cd /data/app/myDirectory && docker stack deploy --compose-file docker-compose.yml foo"' } } }
方案2:here-doc传递多行脚本(适合多步命令场景,可读性强)
如果需要执行的命令较多,挤在单行可读性差,可以用here-doc语法将多行脚本通过标准输入传给远程bash执行,注意<< 'EOF'的单引号不能省略,避免本地shell提前解析脚本内的变量:
stage("deploy") { steps { sshagent(credentials: ['my-sshKey']){ sh ''' ssh -o StrictHostKeyChecking=no myUser@foo.bar.com bash -s << 'EOF' cd /data/app/myDirectory # 可按需添加更多顺序执行的命令 docker stack deploy --compose-file docker-compose.yml foo EOF ''' } } }
方案3:上传脚本后远程执行(适合复杂部署逻辑场景,易维护)
如果部署逻辑涉及条件判断、多文件操作等复杂流程,可以先在代码仓库中维护独立的部署脚本,构建阶段先通过scp将脚本传到远程主机,再SSH调用执行:
stage("deploy") { steps { sshagent(credentials: ['my-sshKey']){ // 给本地部署脚本加执行权限后传到远程临时目录 sh 'chmod +x ./script/deploy.sh && scp -o StrictHostKeyChecking=no ./script/deploy.sh myUser@foo.bar.com:/tmp/' // 执行远程脚本 sh 'ssh -o StrictHostKeyChecking=no myUser@foo.bar.com "/tmp/deploy.sh"' } } }
对应的deploy.sh脚本内容示例:
#!/bin/bash set -e # 任意命令执行失败则退出,避免后续逻辑异常 cd /data/app/myDirectory docker stack deploy --compose-file docker-compose.yml foo
注意事项
- 远程执行
cd操作时必须使用绝对路径,不要依赖SSH登录后的默认工作目录,避免路径不存在报错 - 提前确认SSH登录的远程用户
myUser具备docker操作权限(属于docker用户组),否则会出现docker命令权限不足错误 -o StrictHostKeyChecking=no参数仅建议在内网测试环境使用,生产环境建议提前将远程主机的SSH指纹录入Jenkins Worker节点的known_hosts文件,降低安全风险
内容的提问来源于stack exchange,提问作者Human
相关产品推荐
相关产品推荐

