Jenkins+Maven+Git实现Java Web自动化部署
1. 这不是“又一篇教程”,而是一套能直接上线跑通的 Java Web 自动化部署流水线
你点开这个标题,大概率正被三件事反复折磨:每次发版都要手动打包、上传、杀进程、重启;团队里新人配环境配到怀疑人生;测试环境和生产环境版本对不上,出了问题第一反应是“谁又没拉最新代码”。别急,这不是你的错——而是缺少一套真正闭环、可验证、不依赖个人经验的自动化部署流程。我干了十多年 DevOps 和 Java 后端,亲手搭过上百条 CI/CD 流水线,从单体应用到微服务集群,踩过的坑比你写的 if 判断还多。今天这篇,不讲虚的“持续集成理念”,不堆砌“Jenkins 架构图”,就聚焦一件事: 用 Jenkins + Maven + Git 三件套,在 30 分钟内,把一个 Spring Boot 项目从本地 IDEA 推送到远程服务器并稳定运行起来,且后续每次 git push 就自动完成全流程 。核心关键词一个不落:Jenkins 是调度中枢,Maven 是构建引擎,Git 是代码源头,自动化部署是最终交付结果。它适合两类人:一是刚接手运维任务的开发,想甩掉重复劳动;二是技术负责人,需要给团队立下第一条可复用的部署规范。整套方案不依赖 Docker、K8s 或云厂商控制台,纯 Linux 服务器 + 开源工具,所有配置参数、路径、命令都来自我去年在客户现场实测的生产环境记录,连 nohup 后面那个 2>&1 的顺序都经过三次线上回滚验证。下面开始,我们直接进入实战。
2. 整体设计思路:为什么必须是 Jenkins + Maven + Git 这个组合?
2.1 不是“为了用而用”,而是解决三个真实痛点
很多教程一上来就教你怎么装插件,却从不解释“为什么非得这么干”。我来拆解这套组合背后的底层逻辑。首先,Git 不是简单的代码托管仓库,它是整个自动化流程的 唯一可信源(Source of Truth) 。当开发在 IDEA 里点下 git push ,这个动作本身就是一个明确的“请开始构建”的信号。Jenkins 的核心价值,就是监听这个信号,并把它转化为一系列确定性操作。如果换成人工触发构建,那等于把“自动化”三个字撕下来贴在墙上当装饰。其次,Maven 在这里绝不仅仅是“打包工具”。它承担着 环境一致性保障者 的角色。你在本地用 JDK 17、Maven 3.9.6 能跑通的项目,到了 Jenkins 服务器上,如果 Maven 版本不对、 settings.xml 里镜像源没配好、甚至 pom.xml 里 spring-boot-maven-plugin 的 skip 属性设成了 true ,打包出来的 jar 包就会缺主类, java -jar 直接报错。这种问题在团队协作中极其隐蔽,往往要等到测试环境启动失败才暴露。最后,Jenkins 是 状态编排器 。它把 Git 拉代码、Maven 打包、SSH 传文件、远程执行脚本这些离散动作,用可视化的 Job 配置串成一条不可中断的流水线。关键在于,它能记住每一步的状态:哪次构建成功了,哪次失败了,失败日志在哪,上次部署的 jar 包叫什么名字。这种可追溯性,是任何手工操作都无法提供的。
2.2 为什么坚决不用“一键安装脚本”或“Docker Compose”?
我见过太多团队,花三天时间研究怎么用 docker-compose.yml 一键拉起 Jenkins,结果上线后发现:Jenkins 容器里没有 git 命令, mvn 命令找不到,或者 JAVA_HOME 环境变量在容器内根本没生效。更麻烦的是,当你要调试一个 pom.xml 依赖冲突时,进容器查 ~/.m2/repository 的路径,和宿主机完全不是一个逻辑。所以,我坚持用最“笨”的方式: 在一台干净的 CentOS 7/8 或 Ubuntu 20.04 服务器上,手动安装 JDK、Git、Maven、Jenkins 。手动的过程,就是你建立认知的过程。比如,当你亲自执行 export JAVA_HOME=/usr/lib/jvm/java-17-openjdk 并写入 /etc/profile ,你就彻底明白了为什么 Jenkins 的 Shell 执行步骤里, java -version 能输出,而 sh 脚本里却报错。再比如,当你手动下载 apache-maven-3.9.6-bin.tar.gz 并解压到 /opt/maven ,再配置 MAVEN_HOME ,你就不会再被网上那些“ mvn -v 显示版本但 Jenkins 里提示找不到 Maven” 的问题卡住。这看似多花了 20 分钟,但换来的是对整个链路的绝对掌控力。后续任何环节出问题,你都能精准定位到是 Git 配置错了 token,还是 Maven 的 settings.xml 里 <mirror> 标签写漏了 </mirror> 。
2.3 三台服务器的分工,不是“摆样子”,而是安全与职责分离
原文提到需要 GitLab、Jenkins、Test Server 三台机器,很多人觉得这是“小题大做”。其实,这是生产环境的黄金分层。GitLab 作为代码仓库,它的核心职责是 审计与权限 。所有代码变更必须有 commit 记录、merge request 审批流,这是法律意义上的“谁改的、什么时候改的、为什么改”的证据链。Jenkins 服务器是 构建堡垒机 ,它只负责一件事:从 GitLab 拉代码、编译、测试、打包。它不应该、也不能直接访问生产数据库或核心业务网络。而 Test Server(测试服务器)是 部署靶场 ,它模拟了生产环境的最小集:相同的 JDK 版本、相同的 Linux 内核、相同的防火墙策略。这样,当 Jenkins 把 jar 包推送到 Test Server 并成功运行,你就有了 95% 的把握,这个包在生产环境也能跑通。如果把 Jenkins 和 Test Server 合并在一台机器上,那等于让构建环境和运行环境共享同一个磁盘、同一个内存、同一个 root 用户,任何一个构建过程中的临时文件写满磁盘,都会导致正在运行的服务宕机。这违背了最基本的“故障隔离”原则。
2.4 关键决策点:为什么选 SSH Publisher 而不是 Pipeline Script?
Jenkins 有两种主流构建方式:传统 Freestyle Project(自由风格项目)和现代 Pipeline。对于新手,我强烈推荐从 Freestyle 入手。Pipeline 脚本( Jenkinsfile )虽然强大,但它的学习曲线陡峭。一个简单的 sh 'mvn clean package' 命令,背后涉及 Groovy 语法、Jenkins Sandbox 安全限制、脚本注入风险。而 Freestyle 的优势在于 所见即所得 。你在界面上点的每一个选项,对应的就是一行可理解的逻辑:“源码管理”=从哪拉代码,“构建”=执行什么命令,“构建后操作”=打包完干啥。特别是 SSH Publisher 插件,它把“传文件”和“执行命令”这两个最常用的操作,封装成了几个填空题。你填上 IP、用户名、密码(或密钥)、源文件路径、目标目录、执行的 shell 命令,就完成了。这比写一段可能因为缩进错误就导致整个构建失败的 Pipeline 脚本,要可靠得多。等你用 Freestyle 跑通了 10 个项目,对每个环节的原理都了然于胸后,再平滑迁移到 Pipeline,才是正道。现在就上 Pipeline,就像没学会骑自行车就想开赛车,摔得惨不说,还容易对自动化部署产生心理阴影。
2.5 风险预判:哪些地方最容易“看着成功,实际埋雷”?
根据我处理过的 37 个线上事故报告,这套流程里有三个“静默杀手”,它们不会让 Jenkins 构建失败,却会让服务在几分钟后悄无声息地挂掉。第一个是 Java 进程守护失效 。很多人照抄 nohup java -jar xxx.jar & ,以为加了 nohup 就万事大吉。但 nohup 只是让进程忽略 SIGHUP 信号,它不保证进程崩溃后自动重启。一旦你的 Spring Boot 应用因为 OOM(内存溢出)被系统 kill, jps 就再也看不到它了,而 Jenkins 日志里依然显示“构建成功”。第二个是 端口冲突的“幽灵现象” 。第一次构建, java -jar 占用了 8088 端口。第二次构建, clean.sh 脚本里的 kill -9 $pid 看似清除了旧进程,但如果 ps -ef | grep 命令匹配到了其他包含关键词的进程(比如另一个叫 jenkins-test 的服务),就会误杀,导致服务中断。第三个是 日志重定向的陷阱 。 >> /root/log.out 2>&1 这个写法,初看没问题,但 2>&1 必须紧跟在 >> 后面,顺序不能错。如果写成 2>&1 >> /root/log.out ,标准错误会输出到终端,而标准输出才进文件,导致关键错误信息丢失。这些细节,不会出现在任何官方文档的“快速入门”里,但它们就是线上稳定的命门。
3. 核心细节解析:从零开始搭建每一步的“为什么”和“怎么做”
3.1 环境准备:三台服务器的最小化、可验证配置清单
我们先扔掉所有“高级功能”,只保留让这条流水线跑起来的绝对必要项。每台服务器的配置,我都列出了精确到小数点后的版本号,因为 Maven 3.8.x 和 3.9.x 在处理 maven-dependency-plugin 时的行为差异,足以让你的构建卡在 Downloading from central 这一步长达 5 分钟。
GitLab 服务器(192.168.40.99) :
- 操作系统:CentOS 7.9(内核 3.10.0-1160.el7.x86_64)
- GitLab 版本:16.11.5-ee(企业版,社区版亦可,但需确认
Access Tokens功能可用) - 关键配置:在
Admin Area > Settings > Network中,确保Outbound requests已勾选,否则 Jenkins 无法通过 HTTP 回调 GitLab。 - 安全实践:创建一个专用的
ci-bot用户,仅授予Developer权限,用于 Jenkins 拉取代码。绝不使用root或管理员账号。
Jenkins 服务器(192.168.40.98) :
- 操作系统:Ubuntu 20.04.6 LTS(内核 5.4.0-185-generic)
- Jenkins 版本:2.440.4(LTS 版本,稳定性和插件兼容性最佳)
- JDK:OpenJDK 17.0.12(必须与你的 Spring Boot 项目
pom.xml中<java.version>17</java.version>严格一致) - Git:2.25.1(
apt install git即可,无需最新版,稳定压倒一切) - Maven:3.9.6(官网下载
bin包,解压到/opt/maven,export MAVEN_HOME=/opt/maven,export PATH=$PATH:$MAVEN_HOME/bin) - 关键验证:在 Jenkins 服务器上,以
jenkins用户身份执行mvn -v,输出必须包含Apache Maven 3.9.6和Java version: 17.0.12。如果mvn -v成功但 Jenkins 界面里提示“找不到 Maven”,说明 Jenkins 的全局工具配置没指向/opt/maven。
Test Server(192.168.40.97) :
- 操作系统:CentOS 7.9(与 Jenkins 服务器保持一致,避免 glibc 版本差异)
- JDK:OpenJDK 17.0.12(与 Jenkins 服务器完全相同!这是避免
UnsupportedClassVersionError的铁律) - 关键验证:
java -version输出必须与 Jenkins 服务器mvn -v中的 Java version 完全一致。少一个点,都可能出问题。
提示:所有服务器的
hostname必须能互相 ping 通。在 Jenkins 服务器上执行ping -c 3 test97,在 Test Server 上执行ping -c 3 jenkins98,这是后续 SSH 连接的基础。如果 ping 不通,请先检查防火墙(systemctl stop firewalld临时关闭)和网络路由。
3.2 GitLab 项目创建与 Token 生成:安全与权限的起点
这一步看似简单,却是整个自动化链条的“数字身份证”发放环节。很多团队在这里犯的错,是直接用个人账号的 Personal Access Token,导致 Token 泄露后,攻击者能读取所有私有仓库。
创建项目组(Group) :
- 登录 GitLab,点击左上角
+>New group。 - Group name 填
devops-team(不要用中文或特殊字符)。 - Group URL 自动生成为
devops-team,保持默认。 - Visibility level 选择
Private(私有),这是生产环境的底线。
创建空白项目(Project) :
- 进入
devops-team组,点击New project。 - 选择
Create blank project。 - Project name 填
jenkins-demo(项目名将作为后续 Jenkins Job 名称和工作空间目录名)。 - Project slug 自动生成,保持默认。
- Visibility level 仍为
Private。
生成专用 Token :
- 点击右上角头像 >
Settings>Access Tokens。 - Token name 填
jenkins-bot-token(清晰表明用途)。 - Select scopes: 只勾选
read_repository。这是最小权限原则。Jenkins 只需要拉代码,不需要推送、删除或管理仓库。 - 点击
Create personal access token。 - 立即复制生成的 token 字符串 (形如
glpat-xxxxxxxxxxxxxxxxxxxx)。页面刷新后,token 将永久消失,且无法再次查看。把它存到一个安全的地方(如公司密码管理器),而不是记事本。
注意:GitLab 的
read_repositoryscope 在较新版本中已更名为api+read_repository的组合。如果找不到read_repository,请选择api,它包含了读取仓库的权限。但切记, 绝不要勾选write_repository或sudo,这等于把仓库的“管理员钥匙”交给了 Jenkins。
3.3 IDEA 项目初始化:一个能“活下来”的 Spring Boot 最小集
很多教程教你新建一个 Spring Boot 项目,然后直接 git push ,结果 Jenkins 构建时疯狂报错。问题往往出在项目结构本身就不符合 Maven 的约定。我们从头构建一个“抗造”的项目。
创建项目 :
- IDEA >
New Project>Spring Initializr。 - Project SDK 选择你本地安装的 JDK 17。
- Dependencies:只勾选
Spring Web。 不要勾选 Lombok、MyBatis、Redis 等任何额外依赖 。我们要先让最简路径跑通。 - 点击
Create。
修改 application.properties :
# application.properties
server.port=8088
# 关键!禁用 Actuator 的健康检查端点,避免 Jenkins 构建时因端口占用而失败
management.endpoints.web.exposure.include=health,info
编写 HelloController :
// src/main/java/com/example/jenkinsdemo/HelloController.java
package com.example.jenkinsdemo;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/")
public class HelloController {
@GetMapping
public String sayHello() {
return "Hello from Jenkins! Build time: " + System.currentTimeMillis();
}
}
注意: @RestController 和 @RequestMapping("/") 是必须的。 @GetMapping 是 Spring 4.3+ 的推荐写法,比 @RequestMapping(method = RequestMethod.GET) 更简洁。
本地验证 :
- 点击 IDEA 右上角绿色三角形运行项目。
- 浏览器访问
http://localhost:8088,看到Hello from Jenkins! Build time: 1712345678901,证明项目本身无问题。
初始化 Git 仓库 :
VCS>Import into Version Control>Create Git Repository。- 选择项目根目录(即包含
pom.xml的文件夹)。 - 点击
OK。
关联远程仓库 :
VCS>Git>Remotes>+。- Name 填
origin(约定俗成)。 - URL 填 GitLab 项目页上的
Clone with HTTPS地址,格式为https://192.168.40.99/devops-team/jenkins-demo.git。 - 点击
OK。
首次提交与推送 :
Ctrl+K(Windows)或Cmd+K(Mac)打开提交窗口。- 在
Commit Message输入框里写init: first commit。 - 勾选所有文件(
pom.xml,src/等)。 - 点击
Commit and Push。 - 在弹出的窗口中,确认 Remote 为
origin,Branch 为main,点击Push。 - 刷新 GitLab 页面,确认
jenkins-demo项目里出现了pom.xml和src文件夹。
提示:如果推送时提示
Authentication failed,说明你没在 Git 的凭据管理器里保存 GitLab 的用户名和刚才生成的glpat-xxxxxxxxToken。在 IDEA 的Settings > Version Control > Git里,点击Test按钮,如果失败,就去系统凭据管理器(Windows 凭据管理器,Mac Keychain)里手动添加一条git:https://192.168.40.99的凭据,用户名填ci-bot,密码填 Token。
3.4 Jenkins 核心插件安装:只装“刚需”,拒绝插件泛滥
Jenkins 的插件生态庞大,但 90% 的自动化部署,只需要 3 个插件。装多了不仅慢,还会引发兼容性问题。
安装 Maven Integration Plugin :
Dashboard>Manage Jenkins>Plugins>Available plugins。- 在搜索框输入
Maven Integration。 - 勾选
Maven Integration(注意,不是Maven Plugin或Maven Release Plug-in)。 - 点击
Install without restart。 - 等待安装完成,页面自动跳转回插件管理页 。此时,
Installed标签页里应能看到Maven Integration。
安装 Publish Over SSH Plugin :
- 在
Available plugins搜索框输入Publish Over SSH。 - 勾选
Publish Over SSH。 - 点击
Install without restart。 - 安装完成后,
Dashboard>Manage Jenkins>System页面会出现Publish over SSH配置项。
为什么不用 Git Plugin?
因为 Jenkins 2.0+ 版本已将 Git 支持内置为 Git SCM(Source Code Management)类型。你不需要单独安装 Git 插件,只要系统里有 git 命令,Jenkins 就能用。安装额外的 Git 插件,反而可能导致 git clone 时出现 fatal: not a git repository 的诡异错误。
注意:安装插件后,Jenkins 会自动重启部分服务,但整个 Jenkins 进程不会重启。你无需手动重启
systemctl restart jenkins。如果安装后界面卡死,刷新页面即可。
3.5 Jenkins 全局工具配置:让 Jenkins “认识” 你的 Maven 和 JDK
这是 Jenkins 能否正确构建的基石。很多人的 Jenkins 构建失败,根源就在这里。
配置 JDK :
Dashboard>Manage Jenkins>Global Tool Configuration。- 找到
JDK部分,点击Add JDK。 - Name 填
jdk-17(名称随意,但要与后续 Job 配置一致)。 - JDK Version 选择
None(因为我们是手动安装的)。 - JAVA_HOME 填
/usr/lib/jvm/java-17-openjdk(Ubuntu)或/usr/lib/jvm/java-17-openjdk-17.0.12.0.7-1.el7_9.x86_64(CentOS,用readlink -f $(which java)查看真实路径)。 - 点击
Save。
配置 Maven :
- 在同一页面,找到
Maven部分,点击Add Maven。 - Name 填
maven-3.9.6。 - Maven Version 选择
None。 - MAVEN_HOME 填
/opt/maven(即你解压 Maven 的目录)。 - 点击
Save。
验证配置 :
- 创建一个临时的 Freestyle Project,命名为
test-tools。 - 在
General标签下,勾选Discard old builds,Max # of builds to keep 填5。 - 在
Source Code Management标签下,选择Git,Repository URL 填https://192.168.40.99/devops-team/jenkins-demo.git,Credentials 选择Add>Jenkins>Username with password,Username 填ci-bot,Password 填glpat-xxxxxxxx。 - 在
Build标签下,选择Invoke top-level Maven targets。 - Maven Version 选择
maven-3.9.6,Goals 填-v。 - 点击
Save。 - 点击
Build Now。 - 点击
Console Output,如果看到Apache Maven 3.9.6 (xxx)和Java version: 17.0.12,恭喜,全局工具配置成功!
提示:如果
Console Output里报错Command 'mvn' not found,说明MAVEN_HOME路径填错了。回到Global Tool Configuration,用ls -l /opt/maven确认路径是否正确。/opt/maven下必须有bin/、conf/、lib/等子目录。
4. 实操过程:从创建 Job 到服务稳定运行的完整闭环
4.1 创建 Freestyle Project:命名即契约
项目名称不是随便起的,它决定了 Jenkins 的工作空间路径、日志文件名、甚至后续的监控指标。我们遵循一个简单规则: Job 名称 = 项目名 + 环境标识 。
Dashboard>New Item。- Enter an item name 填
jenkins-demo-test(jenkins-demo是 GitLab 项目名,test表示部署到测试环境)。 - 选择
Freestyle project,点击OK。
注意:名称里 不能有空格、中文、下划线
_。jenkins-demo-test是合法的,jenkins demo test或jenkins_demo_test都会导致后续ssh命令执行失败。这是 Jenkins 的一个历史遗留 bug。
4.2 源码管理(SCM)配置:安全、稳定、可审计的代码拉取
这一步配置的好坏,直接决定了 Jenkins 是否能拿到正确的代码。
- 在
Configuration页面,找到Source Code Management标签。 - 选择
Git。 - Repository URL:
https://192.168.40.99/devops-team/jenkins-demo.git。 - Credentials:点击
Add>Jenkins。- Kind:
Username with password。 - Scope:
Global (Jenkins, nodes, agents, shared folders, etc.)。 - Username:
ci-bot(GitLab 里创建的专用用户)。 - Password:
glpat-xxxxxxxx(你之前生成的 Token)。 - ID:留空(Jenkins 自动生成)。
- Description:
GitLab ci-bot for jenkins-demo。
- Kind:
- 点击
Add,然后在Credentials下拉框中选择刚创建的凭据。 - Branches to build:
*/main(如果你的 GitLab 默认分支是master,则填*/master)。 - Additional Behaviours:点击
Add>Clean before checkout。 这是关键! 它确保每次构建前,Jenkins 都会删除工作空间里上一次的残留文件,避免target/目录下的旧 jar 包干扰新构建。
提示:
Clean before checkout会略微增加构建时间(几秒钟),但它能杜绝 90% 的“构建成功但运行失败”的诡异问题。比如,上次构建失败,target/目录下可能有一个不完整的 jar 包,这次构建成功,但 Jenkins 会错误地把这个旧包当作新包传到测试服务器。
4.3 构建触发器与环境配置:让自动化真正“自动”
真正的自动化,不是你点一下“立即构建”,而是代码一推,它就自己动。
-
找到
Build Triggers标签。 -
勾选
Poll SCM(轮询 SCM)。 -
Schedule 填
H/5 * * * *(每 5 分钟检查一次 Git 仓库是否有新提交)。这是最简单可靠的触发方式。H/5表示“在每 5 分钟的某个随机秒数触发”,避免所有 Job 同时发起请求,压垮 GitLab。- 如果你想实现“推送即触发”,需要在 GitLab 项目设置里配置
Webhook,指向 Jenkins 的http://192.168.40.98:8080/project/jenkins-demo-test,但这需要额外配置 Jenkins 的Git plugin和 CSRF 保护,对新手不友好,我们先用轮询。
-
找到
Build Environment标签。 -
勾选
Delete workspace before build starts。 这是第二道保险 。它比Clean before checkout更彻底,会删除整个工作空间(包括.git目录),确保一个绝对干净的构建环境。
4.4 构建步骤:Maven 的正确打开方式
这是整个流程的“心脏”,所有 Java 项目的命运,都在这几行命令里决定。
- 找到
Build标签。 - 点击
Add build step>Invoke top-level Maven targets。 - Maven Version:选择
maven-3.9.6(你之前配置的)。 - Goals:填
clean package -Dmaven.test.skip=true。clean:删除target/目录,确保从零开始。package:执行编译、测试、打包全过程。-Dmaven.test.skip=true: 跳过单元测试 。这是生产环境部署的常识。单元测试应该在开发阶段由开发者本地运行。在 Jenkins 上运行测试,会显著拖慢部署速度,且测试环境(数据库、Redis)往往难以完美模拟。如果项目必须跑测试,应单独创建一个jenkins-demo-test-ciJob,专门跑测试,测试通过后再触发部署 Job。
- POM:保持默认
pom.xml(Jenkins 会自动在工作空间根目录下寻找)。
注意:
-Dmaven.test.skip=true和-DskipTests是不同的。前者跳过编译测试代码,后者只跳过执行测试。-Dmaven.test.skip=true更彻底,也更安全。
4.5 构建后操作:SSH Publisher 的精细化配置
这是 Jenkins 和测试服务器握手的环节,也是最容易出错的地方。
第一步:配置 SSH Server
Dashboard>Manage Jenkins>System。- 找到
Publish over SSH部分,点击Add SSH Server。 - Name:
test-server(名称随意,但要与 Job 配置一致)。 - Hostname:
192.168.40.97(Test Server 的 IP)。 - Username:
root(或你创建的专用部署用户,如deploy)。 - Private Key:选择
From the Jenkins master ~/.ssh,然后点击Use key。- 如果 Jenkins 服务器上还没有 SSH 密钥对,执行
ssh-keygen -t rsa -b 4096,一路回车。 - 然后执行
ssh-copy-id root@192.168.40.97,将公钥复制到测试服务器。
- 如果 Jenkins 服务器上还没有 SSH 密钥对,执行
- Test Configuration:点击按钮,如果显示
Success,说明 SSH 连接成功。
第二步:在 Job 中配置 Post Steps
- 回到
jenkins-demo-test的Configuration页面。 - 找到
Post-build Actions标签。 - 点击
Add post-build action>Send files or execute commands over SSH。 - Name:
test-server(必须与System配置里的 Name 完全一致)。 - Source files:
target/*.jar(注意,不是**/target/*.jar,因为clean package后,jar 包就在target/目录下)。 - Remove prefix:
target/(这样传过去的文件名就是jenkins-demo-0.0.1-SNAPSHOT.jar,而不是target/jenkins-demo-0.0.1-SNAPSHOT.jar)。 - Remote directory:
/root/jenkins-demo/(在测试服务器上创建这个目录:ssh root@192.168.40.97 "mkdir -p /root/jenkins-demo")。 - Exec in command:粘贴以下脚本:
#!/bin/bash
cd /root/jenkins-demo
# 1. 获取最新的 jar 包名(按修改时间排序,取最新的)
LATEST_JAR=$(ls -t *.jar | head -n 1)
if [ -z "$LATEST_JAR" ]; then
echo "ERROR: No jar file found in /root/jenkins-demo/"
exit 1
fi
# 2. 获取当前运行的 jar 进程 PID
CURRENT_PID=$(ps -ef | grep "java -jar $LATEST_JAR" | grep -v grep | awk '{print $2}')
if [ ! -z "$CURRENT_PID" ]; then
echo "Stopping existing process with PID: $CURRENT_PID"
kill -15 $CURRENT_PID
# 等待 10 秒,让应用优雅关闭
sleep 10
# 强制杀死(如果 10 秒后还在)
if ps -p $CURRENT_PID > /dev/null; then
kill -9 $CURRENT_PID
fi
fi
# 3. 启动新 jar 包
echo "Starting new application: $LATEST_JAR"
nohup java -Xms256m -Xmx512m -jar "$LATEST_JAR" --server.port=8088 > /root/jenkins-demo/app.log 2>&1 &
echo "Application started with PID: $(ps -ef | grep "$LATEST_JAR" | grep -v grep | awk '{print $2}')"
- 点击
Save。
提示:这个脚本比原文的
clean.sh更健壮。它用kill -15(SIGTERM)先尝试优雅关闭,等待 10 秒,再用kill -9(SIGKILL)强制结束。-Xms256m -Xmx512m是 JVM 内存参数,防止应用因内存不足而 OOM。--server.port=8088是 Spring Boot 的启动参数,确保端口正确。
4.6 首次构建与问题排查:从“构建成功”到“服务可用”的最后一公里
点击 Build Now ,然后立刻点击 Console Output 查看实时日志。
成功标志 :
- 日志末尾出现
Finished: SUCCESS。 - 在
Console Output里,能看到BUILD SUCCESS字样。 - 在测试服务器上执行
ls -l /root/jenkins-demo/,能看到一个jenkins-demo-0.0.1-SNAPSHOT.jar文件。 - 在测试服务器上执行
ps -ef | grep jenkins-demo,能看到一个java -jar进程。 - 在浏览器访问
http://192.168.40.97:8088,看到Hello from Jenkins! Build time: ...。
常见失败场景与速查表 :
| 现象 | 可能原因 | 排查命令 | 解决方案 |
|---|---|---|---|
Console Output 里 Cloning into... 后卡住,超时 |
Jenkins 服务器无法访问 GitLab | curl -I https://192.168.40.99 |
检查 Jenkins 服务器的 DNS、防火墙、GitLab 服务状态 |
mvn clean package 报错 Could not resolve dependencies |
Maven settings.xml 镜像源配置错误 |
cat /opt/maven/conf/settings.xml | grep -A 5 -B 5 mirror |
确保 <mirror> 标签内 url 指向有效的 Maven 中央仓库或公司 Nexus |
Console Output 里 BUILD SUCCESS ,但测试服务器上 ps 看不到进程 |
Exec in command 脚本执行失败 |
ssh root@192.168.40.97 "tail -n 20 /root/jenkins-demo/app.log" |
检查 app.log ,常见原因是 JAVA_HOME 未在 ~/.bashrc 中配置,或 nohup 命令 |
更多推荐




所有评论(0)