jenkins 默认只构建不部署,需手动配置post-build actions或pipeline脚本执行scp、ssh等操作;常见失败原因包括未定义部署步骤、路径错误、权限不足及未终止旧进程。

Jenkins 本身不自带“自动化部署”功能,它只负责触发、执行和编排任务;真正的部署动作(比如上传文件、重启服务、运行脚本)必须由你显式定义——要么写在构建后步骤里,要么用 Pipeline 脚本控制。没配对的 Post Steps 或没写的 pipeline 阶段,就只是打包完扔在 workspace 里,不会自动上服务器。
为什么 build 成功了但服务没更新?
常见现象:Jenkins 控制台输出 [INFO] BUILD SUCCESS,target/xxx.jar 确实生成了,但远程服务器上的旧进程还在跑,新包压根没传过去。
根本原因在于 Jenkins 默认只做构建(Build),不处理部署(Deploy)。自由风格项目里,必须手动填 Post-build Actions → Execute shell 或装插件(如 Publish Over SSH);Pipeline 项目则必须在 stages 里明确写 sh 'scp ...' 或 sh 'ssh user@host "systemctl restart myapp"'。
容易忽略的点:
-
workspace路径不是固定死的,不同任务可能落在/var/lib/jenkins/workspace/xxx或/home/jenkins/workspace/yyy,硬编码路径会失败 - Shell 脚本里没加
set -e,某条命令出错(比如scp权限拒绝)但后续命令仍继续执行,看起来“成功”实则漏步骤 - 没处理旧进程:没
kill -9 $(cat /path/to/app.pid)或systemctl stop myapp,新包覆盖后端口被占,启动失败
自由风格项目怎么加部署步骤?
适用于快速验证或简单单机部署,不用写 Groovy,靠界面勾选+填命令就行。
关键操作:
- 进任务配置页 → 拉到最底下 →
Post-build Actions → Add post-build action → Execute shell - 在脚本框里写真实能跑通的命令,例如:
export BUILD_ID=dontKillMe cd $WORKSPACE/target scp -o StrictHostKeyChecking=no app.jar user@192.168.1.100:/opt/myapp/ ssh -o StrictHostKeyChecking=no user@192.168.1.100 "systemctl restart myapp"
注意:$WORKSPACE 是 Jenkins 内置变量,指向当前任务的工作目录,比硬写路径安全;StrictHostKeyChecking=no 是为避免首次 ssh 连接卡住,生产环境建议预置 known_hosts。
如果用 Publish Over SSH 插件,得先在 系统管理 → 系统设置 → Publish over SSH 里配好目标服务器的 IP、用户、密钥,再在任务里选对应 Server 和 Remote Directory —— 它底层也是调 scp 和 ssh,只是封装了一层。
Pipeline 项目怎么写可维护的部署流程?
自由风格适合“一次跑通”,Pipeline 才是 CI/CD 的正解:逻辑清晰、版本可控、支持并行、便于加条件判断(比如只在 main 分支才部署到生产)。
一个最小可用的 Jenkinsfile 示例(放在项目根目录):
pipeline {
agent any
environment {
APP_NAME = 'my-springboot-app'
REMOTE_HOST = '192.168.1.100'
REMOTE_USER = 'deploy'
}
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Build') {
steps { sh 'mvn clean package -Dmaven.test.skip=true' }
}
stage('Deploy') {
steps {
sh "scp target/${APP_NAME}.jar ${REMOTE_USER}@${REMOTE_HOST}:/opt/app/"
sh "ssh ${REMOTE_USER}@${REMOTE_HOST} 'systemctl restart ${APP_NAME}'"
}
}
}
}
关键细节:
- 别把密码写进
Jenkinsfile!用 Jenkins 凭据管理(credentialsId)绑定 SSH 私钥,再在sshCommand步骤里引用 -
agent any表示用任意可用节点执行,如果部署目标和 Jenkins 在同一台机器,可改用agent { label 'master' }避免调度开销 - 实际项目应拆更细的 stage,比如
Test、Build Image、Push to Registry,而不是全堆在Deploy里
部署失败时最该查哪三处日志?
别一上来就重跑任务。CI/CD 流程里,90% 的部署失败都卡在权限、路径、环境三件事上。
按顺序查:
- Jenkins 控制台输出(页面上直接可见):看最后一段红字,是不是
Permission denied (publickey)或No such file or directory: target/xxx.jar - 目标服务器的
journalctl -u myapp -n 50:确认进程是否真启动了,还是启动报错退出(比如端口被占、配置文件缺失) - Jenkins 本地的
/var/log/jenkins/jenkins.log:如果连ssh命令都没发出去,可能是 Jenkins 用户没权限读私钥,或docker容器里没装openssh-client
真正难调的不是语法,而是环境差异——Jenkins 用的是 jenkins 用户,而你手动操作时用的是 root 或自己的账号,家目录、PATH、SSH agent 状态全都不一样。每次部署前,先切到 jenkins 用户下手动跑一遍相同命令,比瞎猜快得多。











