☰
CentOS 7 安装 JDK 21 与最新版 Jenkins 完整指南
2026/10/17 11:16:26 网站建设 项目流程

很多跑着 CentOS 7 的老机器,短时间内没法说换就换,可业务又要求用最新版的 Jenkins 来构建 Java 21 项目。yum 默认源里只有老旧 JDK 8,直接装最新 Jenkins 要么缺依赖,要么启动就报 Java 版本不对。这篇文章把我这次在 CentOS 7 上从零装 JDK 21 + 最新版 Jenkins 的完整过程、踩坑点、验证方式都写清楚了,适合那些必须在内网老系统上继续维护 CI/CD 环境的人参考。

1. 为什么非要在这套老组合上硬啃新版本

1.1 最新版 Jenkins 对 Java 的“硬性要求”并不只是建议

很多教程里写“Jenkins 需要 Java 8/11”,但那是老黄历了。新版 Jenkins 从 2.3xx 开始逐步收紧 Java 版本,到了 2.4xx 之后,启动时如果检测到 Java 低于17,直接拒绝运行,日志里会明确提示缺少 Java 17 或更高版本。最新版则把 Java 21 列入了正式支持范围,并且一批新插件(比如某些蓝海相关、Pipeline 增强插件)也把基线提升到了 Java 17 以上。

如果你继续用 JDK 8 去装最新版 Jenkins,yum 安装那一关就可能报Requires: java >= 17,就算用rpm -i --nodeps强行塞进去,启动时也会被 Jetty 直接干掉。这里不是“建议升级”,是“不升就完全跑不起来”。

1.2 CentOS 7 自带源里没有 JDK 21,这是个绕不开的现实

CentOS 7 默认软件仓库里的 Java 最高就是 1.8.0,哪怕你换到扩展源,也很难找到现成的 JDK 21 包。官方停止维护后,默认的 CentOS 仓库访问经常会失败,更不用说提供新版本 JDK 了。

所以唯一的靠谱方案就是手动下载 JDK 21 的二进制压缩包,解压到固定目录,再自己配置环境变量和系统级 java 命令。这个方案看着“原始”,但恰恰最适合内网环境:一次拷贝到/opt/java,后面 Jenkins 稳定引用,升级 JDK 时只换目录即可,不依赖网络仓库状态。

1.3 这套组合真实服务于哪些场景

先说清楚,如果你有一台新机器,或者可以接受用容器跑 Jenkins,那完全没必要在 CentOS 7 上折腾这套。我这次非这么做,是因为那台机器上跑着一堆内部定时脚本、老数据库服务,迁移成本很高,只能在这台机器上就地安装新版 Jenkins。

另外还有个典型场景是内网构建环境:代码仓库、制品库都在内网,CI 机器也要放在内网,但它需要编译 Java 21 的项目,因此 Jenkins 本身必须跑在 JDK 21 上,否则无法直接利用 JDK 21 的编译工具链。下面这套安装思路,本质上是给“旧操作系统 + 新版 Java 工具链”这种组合做一个稳妥落地。

2. 动手前必须搞定的三件基础事项

2.1 先把 CentOS 7 的软件源换到可用的归档源

如果直接在干净 CentOS 7 上执行yum install -y wget,很可能提示找不到镜像,原因是默认的 CentOS 7 仓库已经从主镜像站下线,进入归档状态。这不是你网络问题,而是源本身失效了。

解决办法是换到还在维护的归档源或者国内镜像站。操作流程很简单:

# 备份原始源配置 mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/CentOS-*.repo /etc/yum.repos.d/backup/ # 新建一个 base 源文件,地址指向可用的镜像归档目录 vi /etc/yum.repos.d/centos7.repo

文件内容至少需要包含 BaseOS、Updates、Extras 三部分,比如:

[base] name=CentOS-7 - Base baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.9.2009/os/x86_64/ gpgcheck=0 enabled=1 [updates] name=CentOS-7 - Updates baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.9.2009/updates/x86_64/ gpgcheck=0 enabled=1 [extras] name=CentOS-7 - Extras baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.9.2009/extras/x86_64/ gpgcheck=0 enabled=1

写完后yum clean all && yum makecache。这一步不做,后面所有 yum 操作都会卡住。我建议顺手把wget、vim、tar都装好,后面要用。

2.2 清干净系统里的旧 JDK 残留

CentOS 7 默认会带 OpenJDK 1.8.0,如果不卸载干净,后面配置 JDK 21 时会出现一个很隐蔽的问题:java -version明明显示 21,但 Jenkins 通过系统alternatives调用时,又可能找到/usr/bin/java这个老入口,结果启动依旧失败。

先检查残留:

rpm -qa | grep -E 'openjdk|java-1.8|jre' alternatives --display java

找到列表里的 OpenJDK 相关包后卸载掉:

yum remove -y java-1.8.0-openjdk.x86_64 java-1.8.0-openjdk-devel.x86_64

再检查/etc/profile.d/下有没有以前写入的 JAVA_HOME 旧配置,有的话一起清理。这一步别偷懒,我见过太多案例,就是java -version正常但服务起不来,最后定位到是系统级 JAVA_HOME 路径还指着老版本。

2.3 确认资源与端口,避免启动到一半挂掉

Jenkins 本身不重,但加上构建任务后内存压力不小。建议这台机器至少 2GB 内存,给 Jenkins JVM 分配 1GB 以上。磁盘方面,/var/lib/jenkins是主目录,插件、构建日志、工作区都在这,最好预留 5GB 以上,如果平时构建任务多,20GB 都不嫌多。

端口方面,新版 Jenkins 默认监听8080,用ss -lntp | grep 8080提前确认没被占用。还有两个容易忽略的检查:防火墙是否开启firewalld,以及 SELinux 状态getenforce。这两项都放到最后排错时再看,但提前了解能节省大量时间。

3. JDK 21 安装的正确姿势:压缩包加完整环境配置

3.1 下载 OpenJDK 21 二进制包而不是 RPM

前面说过 CentOS 7 仓库里没有现成的 JDK 21,所以只能下压缩包。选择发行版时我倾向于用公开提供 Linux x64 tar.gz 的 OpenJDK 长期支持构建包,因为它的目录结构固定、授权清晰、升级也方便。

下载时注意架构,服务器通常是 x86_64,确认uname -m输出再选择对应包。下载完成后把压缩包放到/opt/java目录:

mkdir -p /opt/java && cd /opt/java wget --no-check-certificate <JDK21-tar.gz-download-url> tar -xzf jdk-21_linux-x64_bin.tar.gz ls -l /opt/java/

解压出来的目录一般是jdk-21开头的版本号格式。为了让后面的路径稳定,我建议再建立一个无版本号的软链接,比如/opt/java/jdk21,这样 Jenkins 配置里指向的路径不会因为 JDK 补丁版本升级而变化。

3.2 配置 JAVA_HOME 和系统级 java 命令

环境变量写在/etc/profile.d/java21.sh里,这样所有用户登录都能生效:

cat > /etc/profile.d/java21.sh <<'EOF' export JAVA_HOME=/opt/java/jdk21 export PATH=$JAVA_HOME/bin:$PATH EOF source /etc/profile.d/java21.sh java -version

如果java -version输出的还是老版本,说明/usr/bin/java依然指向旧链接。此时直接用update-alternatives把新 JDK 注册成系统默认:

update-alternatives --install /usr/bin/java java /opt/java/jdk21/bin/java 210 update-alternatives --set java /opt/java/jdk21/bin/java update-alternatives --install /usr/bin/javac javac /opt/java/jdk21/bin/javac 210 update-alternatives --set javac /opt/java/jdk21/bin/javac

为什么一定做这一步?因为 Jenkins 的 systemd 服务脚本大概率会从alternatives里解析java命令,而不是读取你的/etc/profile。这一步不做,后面很容易出现“终端里 Java 是 21、服务里 Java 是旧版”的精分现场。

3.3 那边要构建 Java 21 项目,Maven 工具链也要对得上

如果你的流水线里要用 Maven 编译 Java 21 工程,记得 Maven 版本不能太老。Maven 3.8 以前的版本对--release 21支持不完善,建议至少用 Maven 3.9.x。解压 Maven 后同样配置MAVEN_HOME和PATH,然后执行mvn -version,确认输出里绑定的 Java 版本是 21。

另外pom.xml里最好使用:

<properties> <maven.compiler.release>21</maven.compiler.release> </properties>

而不是maven.compiler.source/target=21。原因很简单:release方式会强制 javac 使用 JDK 21 的 API 基线,避免误用了未来 JDK 新方法后,跑到生产 JDK 21 环境却报找不到符号的问题。这一点属于老手也会踩的坑,提前写好能省很多排查时间。

4. 安装最新版 Jenkins:从仓库配置到 systemd 启动

4.1 官方 yum 仓库还是 RPM 包,两条路怎么选

安装 Jenkins 有两条常见路线:添加官方 yum 仓库后用yum install,或者直接下载对应版本的 RPM 包安装。

如果你的内网环境能够访问 Jenkins 官方软件包站点,推荐用 yum 仓库。它能自动解决依赖,后续升级也方便,只需要改版本号即可。如果网络受限,则用 RPM 包离线安装,好处是版本完全可控,坏处是要自己处理依赖和签名校验。

我这次选择了 yum 仓库方式,但提前把 GPG key 导入,避免安装时报公钥错误。

4.2 添加仓库并执行安装,注意依赖报错的真正含义

直接看操作:

curl -fsSL https://pkg.jenkins.io/redhat-stable/jenkins.repo -o /etc/yum.repos.d/jenkins.repo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key yum install -y jenkins

如果执行yum install时提示Requires: java >= 17,说明系统当前的 Java 配置仍然不是 17 或 21。这时候先别急着--nodeps硬装,优先回到第 3 节,把update-alternatives里的java指向确认清楚。因为 Jenkins 的 RPM 包在做依赖检测时,主要看的就是系统默认java版本。

实在无法解决时,可以下载 RPM 后用rpm -ivh --nodeps安装,但接下来必须手动修改服务配置,保证服务启动时能找到 JDK 21,否则系统d服务必挂。

4.3 一定要改的启动配置:JENKINS_JAVA_CMD

新版 Jenkins 安装完成后,主配置文件在/etc/sysconfig/jenkins。里面有一个参数特别关键:JENKINS_JAVA_CMD。很多安装教程根本没提这个参数,导致明明java -version是 21,Jenkins 服务却启动失败。

建议打开/etc/sysconfig/jenkins,确认有这样的配置:

JENKINS_HOME="/var/lib/jenkins" JENKINS_USER="jenkins" JENKINS_PORT="8080" JENKINS_JAVA_CMD="/opt/java/jdk21/bin/java" JENKINS_JAVA_OPTIONS="-Djava.awt.headless=true -Xms512m -Xmx2048m"

然后把 Jenkins 服务设置为开机启动并启动:

systemctl daemon-reload systemctl enable jenkins systemctl start jenkins systemctl status jenkins

如果启动失败,立刻看日志:

journalctl -u jenkins --no-pager -n 50

常见报错有两种:一种是Failed to detect Java version,说明JENKINS_JAVA_CMD路径写错了,或者该路径下的java没有执行权限;另一种是Cannot allocate memory,说明JENKINS_JAVA_OPTIONS里的-Xmx超过了机器可用内存,把-Xmx2048m调低即可。

5. 首次启动后的初始化:解锁密码、URL 路径、插件源

5.1 新版本访问地址不再是 /jenkins

Jenkins 服务起来后,浏览器访问http://服务器IP:8080/就能看到解锁页面。注意新版 Jenkins 默认部署路径就是根路径/,不再有老版本常见的/jenkins上下文路径。这个改动困扰过不少人,明明服务起来了,访问/jenkins却 404。

首次登录需要的管理员密码在这一行命令里:

cat /var/lib/jenkins/secrets/initialAdminPassword

拿到后粘贴进解锁页。之后的“自定义插件”页面建议先跳过,等进入系统后再手动安装插件,避免首次安装一堆插件耗时很久,而且某些插件版本与最新核心的兼容性不一定会提示。

5.2 顺手把插件更新站点切成国内镜像

如果机器能访问外网,直接装插件一般没问题。内网机器通常访问 Jenkins 官方更新服务器很慢,某些网络环境下还会超时。这时把更新站点换成国内镜像能省很多时间。

修改文件/var/lib/jenkins/hudson.model.UpdateCenter.xml,把 URL 改掉:

<?xml version='1.1' encoding='UTF-8'?> <sites> <site> <id>default</id> <url>https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</url> </site> </sites>

修改完重启 Jenkins:

systemctl restart jenkins

这里有个细节:改完文件后立刻去后台看“插件管理-可用插件”,如果列表还是空,等两三分钟再刷新。更新站点连接初始化需要一点时间,不用急着重启第二次。

5.3 第一批插件装什么,怎么避免装出一堆问题

插件不是越多越好,装多了 Jenkins 启动时间直线上升。我的建议是第一波只装这些:

  • Chinese中文语言包
  • Credentials Binding或Credentials(管理账号密钥)
  • Git/Git client(代码拉取基础)
  • Pipeline(声明式流水线必备)

安装完成后,在“系统管理 - Tools” 里能看到 JDK 配置入口。这里不要选“Install automatically”,因为你已经有本地 JDK 21,直接选择“立即安装”并填写JAVA_HOME=/opt/java/jdk21。这样 Jenkins 的全局工具链就指向了真实存在的 JDK,而不是下载一个可能失败的远程包。

6. 用一条真实 Pipeline 验证 JDK 21 全程可用

6.1 在全局工具配置里登记 JDK 21

进入系统管理 - 全局工具配置,找到 JDK 安装区,点击“新增 JDK”,取消勾选“自动安装”,名称填JDK21,JAVA_HOME填/opt/java/jdk21。

这里强调名称“JDK21”并不是随意的,Pipeline 里的tools段会引用这个名字,写错会直接报错说找不到对应工具。保存后再确认一次java -version命令能在这个 JDK 目录下正常输出。

6.2 最小流水线:确认 java 与 javac 都来自 JDK 21

新建一个任务,类型选“流水线”,然后直接粘贴这段:

pipeline { agent any tools { jdk 'JDK21' } stages { stage('check_version') { steps { sh 'java -version 2>&1' sh 'javac -version 2>&1' sh 'echo $JAVA_HOME' } } } }

保存后立即构建。看控制台输出,如果java -version显示类似openjdk version "21.0.x",同时javac -version也是 21,那说明 Jenkins 启动服务和构建节点都已经跑在 JDK 21 上了。

这一步非常重要,因为仅仅“Jenkins 服务本身启动成功”并不代表构建环境里能用 JDK 21 编译项目。很多环境里服务端是 JDK 17、Agent 是 JDK 8,构建时就去到老 JDK,这种割裂才是真正难查的问题。

6.3 编译 Java 21 项目时常见的两个报错与处理

如果后面的 Maven 构建报invalid target release: 21,基本可以断定是 Maven 编译器插件版本太老。解法是把maven-compiler-plugin升到较新版本,或直接在pom.xml里声明:

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.13.0</version> </plugin>

另一个常见报错是cannot find symbol,并且符号来自 JDK 基础类。这类问题通常不是 Jenkins 或 Maven 的事,而是源文件里用了 JDK 21 新 API,但编译时指定的release没到 21。检查maven.compiler.release是否正确设置为 21。你会发现,大部分“Jenkins 装好了却构建不了”的问题,都是因为编译工具链版本不匹配,而不是 Jenkins 本身有问题。

7. 杂七杂八的坑:防火墙、权限、内存、升级备份

7.1 防火墙和 SELinux 要一起查,别单看一个

服务启动成功但外部访问不了时,优先看防火墙:

systemctl status firewalld firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --reload

如果防火墙没问题,再检查 SELinux。CentOS 7 默认安装时通常开启 SELinux,端口被拦截后 Jenkins 日志里可能看不出异常。这时候用getenforce查看当前状态,如果是Enforcing,先临时切到宽松模式做验证:

setenforce 0 systemctl restart jenkins

如果关闭后访问成功,说明是 SELinux 策略拦截。建议不要长期关闭,而是查一下实际被拒绝的日志:

audit2why -a

根据提示放行端口即可。我见过的案例里,绝大多数是 8080 端口不在默认 HTTP 端口列表的问题,放行http_port_t相关端口就能解决。

7.2 Jenkins 用户权限与目录所有权

安装后/var/lib/jenkins目录属主必须是jenkins用户,否则写入时会报权限错误。用以下命令修正:

chown -R jenkins:jenkins /var/lib/jenkins chmod -R u+rwx /var/lib/jenkins

如果你手动改过hudson.model.UpdateCenter.xml或者拷贝过credentials.xml,同样要注意这些文件的属主。最常见的权限问题就是:在 root 下写了文件,重启 Jenkins 后因为无法读取而报错,日志里会出现Access denied之类提示。

7.3 内存参数别照抄,要根据机器实际情况来

/etc/sysconfig/jenkins里的JENKINS_JAVA_OPTIONS默认给的内存可能不够构建高峰期使用。我个人习惯设为-Xms512m -Xmx2048m,但如果测试机器只有 2GB 内存,这个设置会顶着物理内存上限跑。可以先free -m看一下可用内存,再决定 Xmx 值。

还有个容易被忽略的点:可以给 JVM 加上-XX:+UseG1GC,G1 在 Java 21 上本来就是默认垃圾收集器,不写也行,但容器或老内核上显式指定更稳定。

7.4 “最新版”升级之前,备份比什么都重要

最新版 Jenkins 意味着后面还会频繁有小版本更新。每次升级前,我建议做三件事:备份/var/lib/jenkins下config.xml、credentials.xml、secrets/、plugins/、jobs/;执行yum list available jenkins确认要升级到的具体版本;读一下官方升级日志,确认当前插件是否全部兼容。

实际升级命令:

yum install -y jenkins-2.4xx.x systemctl restart jenkins

升级后启动慢是正常的,但要重点看日志里有没有插件加载失败。一旦某个核心插件与新版本不兼容,环境可能直接无法进入系统。这种情况下别慌,把备份目录恢复回去,再重新启动即可。我吃过“不备份直接升级”的亏,后来老老实实加了个定时备份脚本,才解决了这种焦虑。

最后说一条最实用的个人建议:每次在这类老系统上装完环境,立刻把 JDK 路径、/etc/sysconfig/jenkins关键参数、端口依赖、升级日期记录到运维文档里。不要想着“反正装完就不管了”,半年后你再回头看,文档能帮你省下大半天排查时间。这套东西不难,难的是把环境从“能跑”维护成“长期可跑”,一步到位写清楚,比什么都强。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询