先说一下写这篇的动机。做 Java 项目最烦的就是手动发版本地mvn clean package、传包到服务器、备份旧包、重启服务一套流程少说十分钟中间哪个环节出错还得重来。后来我把 CI 这一环接上了 Jenkins让 Gitee 上每次 push 都自动触发构建代码入库即出包省下来的时间非常可观。这篇就完整记录我在 Centos7 上从零搭建这套环境的过程环境组合是Centos7 JDK 1.8 Jenkins 2.346 Maven Git Gitee。网上围绕这个主题的教程很零散而且不少在版本兼容性上翻车特别是 Jenkins 新版本和 JDK8 之间的兼容性坑。我特意选了 Jenkins 2.346 系列这是官方最后一个能安心跑在 JDK8 上的稳定版本线对大多数还在用 Java 8 的存量项目非常合适。文章从服务器准备讲起覆盖 JDK、Jenkins、Maven、Git 的安装配置一直到和 Gitee 仓库打通、跑通一次自动构建适合刚接触 CI/CD 的开发测试以及想在公司内网快速落地一套构建环境的运维同学。跟着操作基本能一次跑通中途可能会踩的坑我也一并写了。1. 版本选型与安装思路为什么是 JDK8 Jenkins 2.3461.1 关键版本兼容性不要在新版上死磕 JDK8很多人上来就装最新版 Jenkins然后发现项目是 JDK8 的构建时各种UnsupportedClassVersionError或者 Jenkins 本身起都起不来。原因很直接Jenkins 从 2.357 这一代开始把运行所依赖的 Java 最低版本提到了 11越往后越不再照顾 Java 8。如果你还在维护老项目最好的选择不是去追新而是锁定 2.346 这条稳定线。为什么选 2.346 而不是最新的 2.3xx 或者 2.4xx因为 2.346 系列是社区公认的最后一条默认兼容 JDK8 的稳定版本线配套的插件生态也成熟。我用的具体版本是 2.346.3这是 2.346 生命周期内较新的修复版本安全性和稳定性都有保证。项目跑在 JDK8 上Jenkins 本身也用 JDK8 启动这样整条构建链路的环境是一致的排查问题的时候少一层“版本不对”的干扰。Maven 版本也要匹配 JDK8。Maven 3.6.3 是经典选择官方明确支持 JDK8而且被大量项目验证过。Maven 3.8 以上的版本虽然也能跑在 JDK8 上但没必要为了一时新意去冒兼容性风险。Git 客户端用 Centos7 自带的 1.8.3.1 就够了拉取 Gitee 仓库、切换分支、打标签这些基础操作完全够用不需要额外编译新版本。1.2 服务器准备与目录规划先想清楚再动手安装前先把服务器环境理顺能省掉后面很多麻烦。我用的是 Centos7 最小化安装装完第一件事是把系统源切到国内镜像不然yum install能慢到让人怀疑人生。然后是目录规划建议统一规范方便以后维护JDK 放/usr/local/java/Maven 放/usr/local/maven/Jenkins 的 war 包放/opt/jenkins/Jenkins 的工作目录JENKINS_HOME用/var/lib/jenkins/Maven 本地仓库缓存独立放/data/maven-repo/为什么要单独规划 Maven 本地仓库因为第一次构建会下载大量依赖 jar 包如果默认放在 Jenkins 用户家目录的.m2/repository下一方面后续想清理不方便另一方面如果换用户执行构建又得重新下载一轮。独立目录的好处是多个用户、多个任务可以共享同一份依赖缓存备份和清理也直观。防火墙和 SELinux 也需要处理。如果是自己学习用的测试机可以直接systemctl stop firewalld加setenforce 0省心如果是在生产环境我建议只放行 8080 端口而不是粗暴关闭防火墙。SELinux 这块Centos7 默认 enforcing 会对 Jenkins 读写某些目录有影响稳妥做法是先在测试环境关闭跑通后再根据实际日志逐个放行。下面给一组常用的放行命令# 放行 8080 端口 firewall-cmd --permanent --add-port8080/tcp firewall-cmd --reload # 临时关闭 SELinux重启前有效 setenforce 02. JDK 1.8 安装与环境变量配置2.1 用 tar.gz 方式安装 JDK避免 yum 版本混乱Centos7 上安装 JDK 有几种方式yum install java-1.8.0-openjdk、用 Oracle JDK 的 rpm 包、或者用 tar.gz 解压。我最推荐的是 tar.gz 解压方式原因有三第一目录结构完全可控JAVA_HOME 指向哪里一目了然第二不依赖系统包管理不会出现多个 JDK 版本互相干扰第三卸载时删目录就行干净利落。我安装的是jdk-8u202-linux-x64.tar.gz。为什么选 8u2028u211 开始 Oracle JDK 的授权条款发生了变化8u202 被普遍认为是最后一个“技术圈默认使用”的 Oracle JDK 8 版本。如果你用的是 OpenJDK就无所谓这个版本卡点但目录结构可能略有差异。下载地址建议用国内镜像Oracle 官网现在下载需要登录容易卡在账号环节。可以用华为云镜像这类国内源下载命令如下mkdir -p /usr/local/java cd /usr/local/java wget https://repo.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz tar -zxvf jdk-8u202-linux-x64.tar.gz解压完成之后确认/usr/local/java/jdk1.8.0_202目录存在。如果下载失败可以换一个镜像站或者用本地下载后再通过scp/rz上传到服务器关键是拿到 tar.gz 包后面的步骤完全一样。2.2 JAVA_HOME 环境变量配置与验证JDK 解压完只是第一步接下来要配置环境变量。打开/etc/profile文件在末尾追加以下内容cat /etc/profile EOF export JAVA_HOME/usr/local/java/jdk1.8.0_202 export PATH$JAVA_HOME/bin:$PATH export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar EOF source /etc/profile为什么把环境变量写到/etc/profile而不是~/.bashrc因为 Jenkins 的 systemd 服务不读这两个文件但后续在命令行里调试 java、mvn 命令时/etc/profile对所有登录用户都生效更适合这类全局工具。CLASSPATH那一行在 JDK9 以后已经不需要了但 JDK8 时代很多项目还是会引用写上也无害。配置完成后验证echo $JAVA_HOME java -version javac -version如果之前服务器上装过 openjdkjava -version可能会显示系统的 openjdk 版本。这时可以用alternatives --config java切换默认版本或者保证 PATH 环境变量中$JAVA_HOME/bin排在/usr/bin前面。我遇到过一次 source 之后当前终端正常新开终端又变回 openjdk 的情况后来发现是 bash 的hash缓存了旧命令路径执行hash -r清一下就好。2.3 环境变量不生效的排查思路环境变量不生效是高频问题总结下来无外乎几种原因。第一种改完/etc/profile后没有重新登录新开的终端如果是图形终端或某些非登录 shell不会主动读取/etc/profile这时要么执行source /etc/profile要么重新 SSH 登录。第二种系统中存在多个 JDKwhich java发现指向的是/usr/bin/java而不是$JAVA_HOME/bin/java需要用alternatives调整或者调整 PATH 顺序。第三种某些服务进程是启动时才读取环境变量的修改完环境变量后旧进程必须重启才生效比如后面要讲的 Jenkins 服务。还有一个很容易被忽略的细节如果你把 JDK 解压到了/root或者其他管理员目录下tomcat、jenkins 这类以普通用户身份运行的程序可能会因为权限不足读不到。所以 JDK 这种全局工具统一解压到/usr/local/下面比较稳妥普通用户至少要有可读和可执行权限。3. Jenkins 2.346 安装与初始化3.1 用 war 包 systemd 部署锁定版本更可控安装 Jenkins 常见有 yum 源安装和 war 包部署两种方式。yum 方式看似省事但有个很现实的问题Jenkins 官方 yum 源当前已经切到新版本系列你yum install装出来的大概率不是 2.346而是要求 JDK11 的新版本和我们要锁定的 JDK8 环境直接冲突。所以我强烈建议用 war 包方式版本完全自己控制配合 systemd 管理也有模有样。先创建目录、下载 war 包mkdir -p /opt/jenkins /var/lib/jenkins /var/cache/jenkins/war cd /opt/jenkins wget https://get.jenkins.io/war-stable/2.346.3/jenkins.war如果官方下载比较慢可以从清华镜像下载wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/war-stable/2.346.3/jenkins.war然后创建 Jenkins 运行用户并授权目录useradd -m -s /bin/bash jenkins chown -R jenkins:jenkins /var/lib/jenkins /var/cache/jenkins /opt/jenkins接下来写 systemd 服务文件/etc/systemd/system/jenkins.service[Unit] DescriptionJenkins Continuous Integration Server Afternetwork.target [Service] Userjenkins Groupjenkins EnvironmentJENKINS_HOME/var/lib/jenkins EnvironmentJAVA_HOME/usr/local/java/jdk1.8.0_202 ExecStart/usr/local/java/jdk1.8.0_202/bin/java -Xms512m -Xmx1024m -Duser.timezoneAsia/Shanghai -Dfile.encodingUTF-8 -jar /opt/jenkins/jenkins.war --httpPort8080 --webroot/var/cache/jenkins/war Restarton-failure RestartSec10 WorkingDirectory/var/lib/jenkins [Install] WantedBymulti-user.target这个文件里有几个细节值得说明。EnvironmentJAVA_HOME...是必须的因为 systemd 启动的进程不会读取/etc/profile不以这种方式传进去Jenkins 就找不到 JDK。-Duser.timezoneAsia/Shanghai解决 Jenkins 页面时区显示 UTC 的问题-Dfile.encodingUTF-8解决构建日志中文乱码的问题这两个参数建议直接写死在启动命令里。启动和设置开机自启systemctl daemon-reload systemctl start jenkins systemctl enable jenkins查看服务状态systemctl status jenkins。如果启动失败用journalctl -fu jenkins看详细日志大部分问题都能在这里看到原因。3.2 初始化 Jenkins先不装推荐插件浏览器访问http://服务器IP:8080第一次进入会要求输入解锁密码。密码存放在 Jenkins 工作目录下cat /var/lib/jenkins/secrets/initialAdminPassword把输出的密码复制进去进入自定义插件安装页面。这里我建议不要选 “Install suggested plugins”推荐插件数量多、耗时长在国内网络环境下很容易卡在下载步骤。直接选 “Select plugins to install”手动选择几个刚需插件——Git、Timestamper、Gitee 这些后面会用到。其他插件后续在 Manage Plugins 里按需安装就行。插件安装完成后创建管理员账号填写用户名密码邮箱。这里有个小坑保存 Jenkins URL 时默认往往填的是http://localhost:8080如果你后续要配置 Gitee Webhook这个地址必须是其他机器能访问到的地址建议直接改成服务器公网 IP 或者内网可访问的地址不然后面回调会打到 localhost 上。3.3 时区与国内插件源加速初始化完成后第一件事就是处理时区和插件源。时区方面如果 systemd 配置里已经带了-Duser.timezoneAsia/Shanghai重启后页面就是北京时间。如果没配可以在 Manage Jenkins → Script Console 里执行System.setProperty(org.apache.commons.jelly.tags.fmt.timeZone, Asia/Shanghai) System.setProperty(user.timezone, Asia/Shanghai)插件源加速也一样重要。默认插件源在海外安装插件慢不说还经常超时失败。在 Manage Jenkins → Manage Plugins → Advanced 页面把 Update Site 改成清华镜像https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json如果之前已经拉取过插件元数据/var/lib/jenkins/updates/default.json里还存着旧的下载地址可以用 sed 把下载域名替换成镜像地址sed -i s#https://updates.jenkins.io/download#https://mirrors.tuna.tsinghua.edu.cn/jenkins#g /var/lib/jenkins/updates/default.json改完重启 Jenkins再去安装插件速度会有质的提升。4. Maven 与 Git 的安装配置4.1 Maven 在 Jenkins 里到底负责什么很多刚入门的人会把 Maven 和 Git 搞混这里捋一下。Git 管的是代码版本谁改了什么、分支怎么切换、历史怎么回溯都是 Git 的事Maven 管的是项目构建和依赖它读pom.xml这个“菜谱”从中央仓库“买菜”下载依赖 jar然后“做菜”编译、测试、打包。Jenkins 则是“调度员”它负责在代码变更时喊一声该去拉代码了拉完叫 Maven 干活干完了把产物收起来。所以 Jenkins 所在的机器上必须有 Maven而且 Jenkins 用户要能访问到 Maven 的目录还要能写本地仓库目录。如果 Jenkins 构建时报mvn: command not found大概率就是环境变量只在 root 用户下配了Jenkins 用户根本找不到命令这个下面会细说。4.2 安装 Maven 并配置阿里云镜像Maven 下载同样建议用国内镜像。我在/usr/local/maven目录下安装mkdir -p /usr/local/maven cd /usr/local/maven wget https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz tar -zxvf apache-maven-3.6.3-bin.tar.gz解压后配置环境变量同样追加到/etc/profilecat /etc/profile EOF export MAVEN_HOME/usr/local/maven/apache-maven-3.6.3 export PATH$MAVEN_HOME/bin:$PATH EOF source /etc/profile mvn -version看到输出了 Java version 和 Maven home说明安装成功。但光装完还不够不配镜像的话第一次构建就会卡在从中央仓库下载依赖这一步慢到怀疑人生。修改 Maven 的settings.xmlvi /usr/local/maven/apache-maven-3.6.3/conf/settings.xml把本地仓库路径改成独立目录localRepository/data/maven-repo/localRepository然后在mirrors节点里加阿里云镜像mirror idaliyunmaven/id mirrorOfcentral/mirrorOf namealiyun public/name urlhttps://maven.aliyun.com/repository/public/url /mirror最后创建目录并授权给 Jenkins 用户因为构建时是 Jenkins 用户在写依赖缓存mkdir -p /data/maven-repo chown -R jenkins:jenkins /data/maven-repo4.3 Git 安装与 Jenkins 用户初始化Centos7 安装 Git 很简单yum install -y git git --version版本号是 1.8.3.1别看它老配合 Jenkins 拉取 Gitee 仓库完全没问题。Git 装完后顺手给 Jenkins 用户配置全局身份信息有些 Jenkins 插件需要user.name和user.email才能正常工作su - jenkins -s /bin/bash -c git config --global user.name jenkins su - jenkins -s /bin/bash -c git config --global user.email jenkinsbuildserver.local这一步不是必须的但提前配置可以避免某些插件在构建时因为缺少身份信息报奇怪的错误。5. 将 JDK、Maven、Git 配置进 Jenkins 并与 Gitee 打通5.1 Global Tool Configuration把三个工具登记进 Jenkins系统装了 JDK、Maven、GitJenkins 并不知道路径在哪里需要手动登记。进入 Manage Jenkins → Tools也就是 Global Tool Configuration。JDK 部分点击 Add JDK名称填jdk-1.8关键一步是取消勾选 “Install automatically”。默认勾选后 Jenkins 会尝试自己下载 JDK网络慢外加版本选择麻烦我们既然已经手动装好了就直接把自动安装关掉填 JAVA_HOME 路径/usr/local/java/jdk1.8.0_202。Git 部分在 Git 一栏把 Path to Git executable 填/usr/bin/git。Maven 部分点击 Add Maven名称填maven-3.6.3同样取消 “Install automatically”填 MAVEN_HOME/usr/local/maven/apache-maven-3.6.3。这里多说一句很多教程没提取消自动安装这一步导致配置完保存后 Jenkins 后台尝试下载工具半天没反应还以为卡死了。手动装好的工具一定要取消自动安装选项路径填准保存即可。5.2 添加 Gitee 访问凭据推荐用私人令牌Jenkins 要拉取 Gitee 上的私有仓库必须配置凭据。最佳实践不是直接填 Gitee 密码而是用 Gitee 私人令牌好处是可以单独授权、单独吊销不会暴露主账号密码。在 Gitee 网页上头像 → 设置 → 安全设置 → 私人令牌 → 生成新令牌权限勾选 projects 相关的读取权限就行。生成的令牌只会显示一次记得复制保存。然后在 Jenkins 里Manage Jenkins → Manage Credentials → Global credentials → Add credentials类型选 “Username with password”Username你的 Gitee 用户名Password粘贴刚刚生成的私人令牌ID填gitee-token方便后续任务里识别保存后后面新建任务时就能直接选这个凭据了。5.3 新建自由风格任务并跑通一次构建配置完成后新建一个自由风格项目测试一下。在 Jenkins 首页点击 New Item输入项目名称选择 “Freestyle project”确定。源码管理选择 GitRepository URL: https://gitee.com/你的用户名/仓库名.git Credentials: gitee-token Branches to build: */main分支名根据 Gitee 仓库默认分支来如果仓库默认是 master 就填*/master。填完 URL 后如果凭据配置正确一般不会报红色错误。构建环境勾选 “Add timestamps to the Console Output”这样构建日志里会显示时间排查问题方便。构建步骤选择 “Invoke top-level Maven targets”Maven Version选maven-3.6.3Goals填clean packageSettings file选择 “Use custom settings”路径填/usr/local/maven/apache-maven-3.6.3/conf/settings.xml为什么要显式指定 settings.xml因为 Jenkins 运行任务时不一定能读到/etc/profile里的环境变量Maven 默认配置也不一定是我们刚改过的那份。显式指定后阿里云镜像和本地仓库目录就能稳定生效。保存后点击 “Build Now”再点击构建历史里的项目进入 Console Output第一次构建会花不少时间下载依赖看到BUILD SUCCESS就是跑通了。构建产物在这个位置ls -lh /var/lib/jenkins/workspace/项目名称/target/5.4 配置 Gitee Webhook实现 push 自动触发构建手动触发构建只是第一步真正的 CI 是 Gitee 上代码一 pushJenkins 自动构建。使用 Gitee Plugin 可以实现。先在 Manage Jenkins → Manage Plugins 里搜索安装 “Gitee Plugin”然后在 Manage Jenkins → System 页面找到 Gitee Configuration确认链接地址是https://gitee.com保存。打开刚才创建的任务左侧菜单里能看到 “Gitee Webhook” 链接点开会显示回调 URL 和 token形式大致是http://你的Jenkins地址:8080/gitee-webhook/ token: 一串随机字符到 Gitee 仓库页面管理 → WebHooks → 添加 WebHookURL 填上面的回调地址密码推送秘密填上面显示的 token事件勾选 Push保存后可以先点“测试”按钮如果返回正常说明回调通。然后本地git push一次Jenkins 就会自动触发构建。有个前提必须说清楚Jenkins 所在服务器必须能被 Gitee 公网访问到。如果 Jenkins 部署在内网Webhook 回调会失败这种情况暂时只能手动触发或者用定时构建过渡等有了公网地址或反向代理再启用。6. 常见问题与排查经验速查6.1 高频报错与解决对照表整套流程走下来新手容易在这几个地方卡住问题现象常见原因解决办法8080 端口访问超时防火墙未放行 / 云安全组未开放firewall-cmd --permanent --add-port8080/tcp并 reload同时检查云平台安全组解锁密码找不到JENKINS_HOME 路径被修改过find / -name initialAdminPassword全局搜索插件安装慢或失败默认插件源在海外修改 Update Site 为清华镜像修改updates/default.json中的下载域名构建任务里 mvn 命令找不到systemd 或 Jenkins 进程没加载/etc/profile使用 Maven 构建步骤并选择已配置的 Maven而不是在 shell 里写裸命令Gitee 仓库拉取 401/403凭据未配置或 token 权限不足重新添加凭据检查 token 是否勾选了 projects 权限构建日志显示 UTC 时间未设置时区参数在 JVM 启动参数里加-Duser.timezoneAsia/Shanghai后重启中文乱码编码未指定在 systemd 启动参数加-Dfile.encodingUTF-8Maven 配置里也声明 UTF-8Webhook 测试返回 404Jenkins 地址不可公网访问 / Gitee 插件未装确认 Webhook URL 和 token 正确Jenkins 上安装 Gitee Plugin 并配置6.2 三个值得说一说的踩坑经历第一个坑是 yum 源装了新版 Jenkins。早期我图省事直接走 yum结果装出来的 Jenkins 版本要求 JDK11项目环境是 JDK8最后服务起不来。后来统一改用 war 包 systemd 方式固定 2.346.3问题一次解决。现在我对生产环境的工具版本态度很明确锁定版本比追新重要尤其是 CI 这种链条中间环节任何一个依赖版本漂移都可能引发连锁故障。第二个坑是环境变量不生效。我在/etc/profile里配好了 JAVA_HOME命令行测试一切正常结果 Jenkins 服务就是起不来报找不到 Java。查了半天发现 systemd 启动进程不读/etc/profile必须在 service 文件里通过 Environment 参数显式传入。这个问题在 cron 定时任务里也会遇到统一规律是脱离登录 shell 的进程都要显式指定关键环境变量。第三个坑是第一次构建时依赖下载缓慢。当时没用 Maven 镜像构建任务卡在下载依赖停了很久最后超时失败。配置阿里云镜像和独立本地仓库后构建速度提升非常明显。后来我干脆把/data/maven-repo和/var/lib/jenkins/workspace从系统盘挪到了数据盘既避免系统盘空间不足也方便备份。这套环境搭完我的习惯是先手动 Build Now 跑通一次确认 BUILD SUCCESS 再去接 Webhook这样出问题时排查范围更小。后续还可以继续扩展构建完把 war/jar 包通过 Publish Over SSH 推到测试服务器、用流水线把 Jenkinsfile 放进仓库管理、加钉钉或企业微信的通知。先把这篇里的链路跑通后面每一步都是在这个基础上加砖添瓦。