如何在Jenkins多分支流水线中通过SSH发布部署?
部署Spring Boot Jar到Linux服务器的Jenkinsfile配置指南
刚好我之前折腾过类似的配置,这就给你拆解部署阶段的写法,分两种常用方案,你可以根据自己的环境选:
前提准备
- 确保Jenkins服务器能通过SSH无密码登录目标Linux服务器(推荐用密钥对,提前在Jenkins凭证里配置好SSH密钥)
- 目标服务器上提前创建好部署目录(比如
/opt/my-springboot-app),并给Jenkins用户分配相应的读写/执行权限 - 如果想让服务启停更稳定,建议在目标服务器上配置
systemd服务(后面会附配置示例)
方案一:用Jenkins SSH插件(推荐,更简洁易维护)
先去Jenkins插件中心安装SSH Pipeline Steps插件,然后就可以在Pipeline里直接调用封装好的SSH步骤。
以下是完整的Jenkinsfile示例(在你已有的构建阶段后面追加部署阶段):
pipeline { agent any stages { // 你已经正常运行的构建阶段 stage('Build Jar') { steps { sh 'mvn clean package -DskipTests' // 归档Jar包,方便后续回滚或查看 archiveArtifacts artifacts: 'target/*.jar', fingerprint: true } } // 新增的部署阶段 stage('Deploy to Linux Server') { steps { script { // 从Jenkins凭证库获取提前配置好的SSH密钥ID def sshCredentials = credentials('ssh-server-credential-id') // 上传Jar包+执行部署脚本 sshPublisher( publishers: [ sshPublisherDesc( configName: 'My-Linux-Server', // 提前在Jenkins系统配置里添加的SSH服务器连接(填IP、端口、用户名) transfers: [ sshTransfer( sourceFiles: 'target/*.jar', remoteDirectory: '/opt/my-springboot-app', removePrefix: 'target', execCommand: ''' # 1. 备份旧Jar包(可选但推荐,方便回滚) cd /opt/my-springboot-app if [ -f app.jar ]; then mv app.jar app.jar.backup.$(date +%Y%m%d%H%M%S) fi # 2. 重命名新Jar包为统一名称(避免文件名带版本号的麻烦) mv *.jar app.jar # 3. 停止旧服务(用systemd管理的话) sudo systemctl stop my-springboot-app.service # 4. 启动新服务 sudo systemctl start my-springboot-app.service # 5. 检查服务状态,确保启动成功 sudo systemctl status my-springboot-app.service ''' ) ], verbose: true ) ] ) } } } } }
关键细节补充:
systemd服务配置示例(在目标服务器上创建/etc/systemd/system/my-springboot-app.service):
[Unit] Description=My SpringBoot Application After=network.target [Service] User=jenkins WorkingDirectory=/opt/my-springboot-app ExecStart=/usr/bin/java -jar app.jar Restart=always RestartSec=5 # 服务崩溃后5秒自动重启 [Install] WantedBy=multi-user.target
创建后记得执行sudo systemctl daemon-reload和sudo systemctl enable my-springboot-app.service,让服务开机自启。
方案二:用原生scp+ssh命令(无需插件,适合轻量场景)
如果不想装插件,也可以直接用shell命令完成上传和部署:
pipeline { agent any stages { stage('Build Jar') { steps { sh 'mvn clean package -DskipTests' archiveArtifacts artifacts: 'target/*.jar', fingerprint: true } } stage('Deploy to Linux Server') { steps { script { def targetServer = 'jenkins@192.168.1.100' // 目标服务器的用户名+IP def deployDir = '/opt/my-springboot-app' // 获取构建好的Jar包路径(自动处理带版本号的文件名) def jarPath = sh(returnStdout: true, script: 'ls target/*.jar').trim() def sshCredentials = credentials('ssh-server-credential-id') // 1. 上传Jar包到目标服务器 sh "scp -i ${sshCredentials.privateKey} ${jarPath} ${targetServer}:${deployDir}/" // 2. 远程执行部署命令 sh """ ssh -i ${sshCredentials.privateKey} ${targetServer} << EOF cd ${deployDir} # 备份旧包 if [ -f app.jar ]; then mv app.jar app.jar.backup.\$(date +%Y%m%d%H%M%S) fi # 重命名新包 mv *.jar app.jar # 启停服务 sudo systemctl stop my-springboot-app.service sudo systemctl start my-springboot-app.service sudo systemctl status my-springboot-app.service EOF """ } } } } }
注意事项:
- 确保Jenkins用户在目标服务器上有sudo权限(不需要输入密码的话,可以在目标服务器的
/etc/sudoers里添加:jenkins ALL=(ALL) NOPASSWD: /usr/bin/systemctl)
不管用哪种方案,都建议先在测试环境跑一遍,验证上传、启停服务是否正常。如果想更严谨,还可以加个健康检查步骤(比如调用Spring Boot的/actuator/health接口),或者失败时自动回滚到备份Jar包的逻辑。
内容的提问来源于stack exchange,提问作者Madhu Sudhan Reddy
相关产品推荐
相关产品推荐

