☰
Jenkins 2.346.1离线插件包:Java 8环境CI落地指南
2026/10/13 15:07:53 网站建设 项目流程

简介:面向 Jenkins 2.346.1 的离线插件资源包,适用于负责 Jenkins 运维与 Java 8 项目持续集成的开发、运维人员。压缩包共 969 个文件,包括 241 个 jar 库、63 个 jpi 插件本体、147 个 html 说明页、125 个 xml 配置、63 个 properties 属性文件,以及 js、css、svg、png 等前端资源和 48 个 bak 备份文件,整体大小约 214.28MB。插件覆盖 git、credentials、jackson2、jaxb、apache-httpcomponents-client-4-api 等常用组件,可离线解决在线安装失败、插件版本不匹配的问题;替换到 Jenkins 的 plugins 目录并重启即可生效,bak 备份还能在升级异常时快速回滚。包内目录按插件名称组织,便于按需检索和批量部署;MF 清单与 timestamp2 文件保留了插件版本与构建信息,便于核对环境一致性,flow、gif 等辅助文件让目录结构更完整。已有 1371 人学习下载,适合需要固定版本、离线维护插件或批量管理 Jenkins 环境的中高级技术人员,可稳定支撑 Java 8 项目的自动化构建、测试与发布流程。

1. Jenkins 2.346.1 离线插件包:Java 8 时代的 CI 最后舒适区

生产环境里还跑着 JDK 8 的团队,这两年应该都经历过同样的尴尬:内网 Jenkins 想加个插件,在线安装页面转圈半天最后超时;手动下载新版插件塞进plugins目录,重启后日志里抛出一句「requires Jenkins 2.3xx or higher」。为什么会这样?因为 Jenkins 核心从 2.357 开始强制要求 Java 11,很多运维同学还在维护的稳定流水线机器根本没法动 JDK。而 2.346.1 正是 2.346 系列里 Java 8 兼容的最后一个修复版本,也是这类环境里能稳定运行的「最高天花板」。这套资源就是围绕这个版本整理的插件离线包合集,把常用插件连同它们的依赖树一次打包好,让离线环境也能把 CI 真正跑起来。适合还在用 Jenkins + Java 8 的运维、实施和交付团队,尤其是网段隔离、更新中心不可达的机房场景。

2. 为什么卡在 2.346.1:版本边界、插件依赖与资源清单

2.1 Java 8 基线:2.346.x 是最后的宽限期

先说清楚版本边界这件事。Jenkins 核心的 Java 基线变化不是一步到位的,经历了「只支持 Java 8 / 同时支持 8 和 11 / 强制 Java 11」三个阶段。2.346.1 处于第二阶段末尾,官方声明支持 Java 8 和 Java 11,而且 2.346.x 系列持续推进了多个小版本修复,2.346.1 是这套修复线的最后一版。很多团队不是不想升,而是项目里还有大量构建脚本、自定义工具链依赖 JDK 8,agent 节点清一色装的 1.8.0_xxx,强行切 Java 11 会导致一堆老插件和构建任务翻车。

所以这里有个反直觉的结论:不升级到最新版反而是对的。在 JDK 8 约束下,2.346.1 就是兼容性和稳定性之间的最优解。新版本 Jenkins 功能再多,装不上、跑不了,对生产环境就是零价值。

但这带来一个现实问题:插件市场里的新版本插件,很多已经把最低 Jenkins 版本要求抬到了 2.3xx 甚至 2.4xx。如果你的核心是 2.346.1,直接装最新插件大概率被拒。这也是这套资源存在的核心理由——它提供的是「版本经过锁定」的插件集合,而不是简单地「把最新插件打包给你」。

2.2 插件之间互相咬合:依赖树不能只装「主件」

很多初次接触离线插件包的运维同学会犯一个错:以为装插件就是拷贝一个 .hpi 文件。实际上 Jenkins 插件是有依赖链的。每个插件的MANIFEST.MF里有一个Plugin-Dependencies字段,明确声明了它依赖哪些插件、最低版本是多少。比如你要用源码管理插件(git 相关能力),它通常会连带要求凭据类插件、SSH 凭据类插件、SCM API 插件;凭据类插件又会依赖更底层的结构化数据插件。只丢一个主插件进去,重启后大概率看到Failed to load,因为它的依赖兄弟一个都不在。

这也是下载资源时最需要关心的点:一套完整的离线插件包,不是「按需选几个常用插件」就行,而是要把主插件和所有传递依赖一起收进来。我拿到资源后的习惯是先看它的依赖覆盖情况:主插件有哪些、每个主插件对应的依赖插件是否齐全、插件版本之间是否冲突。这套资源里附带了一个插件清单文档,里面按功能组列出了插件名、版本和依赖关系,离线部署前先拿这个清单对一遍,能省掉至少两轮「重启-报错-百度」的循环。

2.3 资源包内的目录与文件:先看清再动手

资源包整体目录结构大致是这样一块:

目录 / 文件作用
plugins/核心插件集,全部为.hpi或.jpi格式,按功能分组放在子目录里
config/Jenkins 运行前的配置模板,包括更新中心指向、启动参数建议
scripts/一键安装、插件清单导出、安装后校验脚本
doc/插件版本清单、依赖关系说明、常见报错对照表

plugins/目录是我最看重的部分。它不仅包含「流水线」「源码管理」「凭据」「构建工具集成」这类高频插件,还把容易遗漏的辅助插件一并收进去了,比如时间戳显示、构建名称设置、配置文件管理这类小插件。这类小插件单个看无关痛痒,但没有它们,流水线终端里看不到时间、构建历史里全是#12这种数字、节点上的配置文件没法统一管理,实际用起来非常别扭。

config/目录里的更新中心模板比较有意思。它把hudson.model.UpdateCenter.xml指向了本地文件路径,这样 Jenkins 启动后不会去外网请求元数据,而是直接读取包内自带的default.json离线索引。这个文件是插件管理页面展示「可安装插件」的数据来源,离线状态下不配它,插件管理页面就是一片空白。后面第三章我会把整个操作链路串起来。

3. 离线安装三连:搬包、改源、重启一次到位

3.1 第一步:确认 JDK 8 与 Jenkins 主程序

先把运行环境确认好,避免装完插件才发现基础环境不对。这里有个运营同学问过我多次的问题:「我机器上同时有 JDK 11 和 JDK 8,Jenkins 会选哪个?」答案是谁在PATH前面就用谁,所以最稳妥的做法是显式指定。

# 检查当前默认 Java 版本 java -version # 如果默认不是 1.8,用 update-alternatives 切换 # 也可以直接设置 JAVA_HOME 后启动 export JAVA_HOME=/opt/jdk1.8.0_202 export PATH=$JAVA_HOME/bin:$PATH # 确认全局环境后启动 Jenkins 主程序 export JENKINS_HOME=/data/jenkins export JENKINS_OPTS="-Djenkins.install.runSetupWizard=false -Dhudson.model.UpdateCenter.never=true" java -jar /opt/jenkins/jenkins.war --httpPort=8080 --prefix=/jenkins

这段命令里有几个点值得说明。-Djenkins.install.runSetupWizard=false是跳过首次启动的初始化向导,离线环境下这步向导会因为网络不通卡你半天,直接关掉;-Dhudson.model.UpdateCenter.never=true是让 Jenkins 彻底放弃外网更新中心请求,防止每次打开插件管理页面都卡到超时。--prefix=/jenkins是给 Jenkins 加一个访问前缀,如果后面要挂统一入口网关,这个参数很有用。第一次启动建议用前台方式运行,确认日志里出现Jenkins is fully up and running再改成nohup后台运行。

3.2 第二步:放置插件文件与权限核对

插件文件放错位置或者属主不对,是离线部署里最常见的返工原因。Jenkins 只能读取$JENKINS_HOME/plugins目录下的插件,不是 war 包解压目录里的那个。

# 解压资源包到临时目录 tar -xzf jenkins-plugins-2.346.1-offline.tar.gz -C /tmp/jenkins-plugins # 把资源包 plugins 目录下的全部插件拷贝到 JENKINS_HOME/plugins mkdir -p /data/jenkins/plugins cp -rf /tmp/jenkins-plugins/plugins/*.hpi /data/jenkins/plugins/ # 统一插件文件属主为 jenkins 用户 chown -R jenkins:jenkins /data/jenkins/plugins chmod 644 /data/jenkins/plugins/*.hpi

这里要提一个容易翻车的细节:Jenkins 加载插件时,如果同一个插件名同时存在.hpi和.jpi两个文件,它优先加载.jpi。你从旧环境迁移时如果plugins目录里已有同名旧插件,直接把新文件拷贝进去并不会覆盖已经存在的.jpi文件,重启后加载的还是旧版本。这会导致你明明换了新插件包,功能却还是老样子。我一般会先在目标环境里清空旧插件目录再整体拷贝:

# 先做一次全量备份,再清空目录 mv /data/jenkins/plugins /data/jenkins/plugins.bak.$(date +%Y%m%d) mkdir -p /data/jenkins/plugins cp -rf /tmp/jenkins-plugins/plugins/*.hpi /data/jenkins/plugins/ chown -R jenkins:jenkins /data/jenkins/plugins

备份目录不删,等新插件确认跑通后再清理,这是一份随时可以吃的后悔药。

3.3 第三步:把更新中心指向本地资源

插件文件放好了,接下来要让 Jenkins 的插件管理页面能认到本地索引。离线环境下如果不做这一步,打开「系统管理 → 插件管理」会看到可用插件列表为空,因为 Jenkins 默认会去官方更新中心拉取update-center.json。资源包的config/目录里已经准备好了改写后的更新中心配置,直接复制过去即可。

<?xml version="1.0" encoding="UTF-8"?> <sites> <site> <id>default</id> <url>file:///data/jenkins-update-center/update-center.json</url> <!-- 离线资源包自带索引,指向本地文件,不再访问外网 --> </site> </sites>

把这个文件放到$JENKINS_HOME/hudson.model.UpdateCenter.xml位置,然后重启 Jenkins。这里有一处需要注意:URL 里的路径必须是存放update-center.json的绝对路径,而且 Jenkins 运行用户(通常是jenkins)要有该文件的读取权限。文件格式本身比在线模式简单,不需要签名字段,因为是我们自建的本地源。

启动完成后,打开插件管理页,能看到「可选插件」列表里出现了资源包索引里的插件项,说明本地源生效了。到这一步,离线安装的骨架已经完整:插件文件就位、依赖链完整、更新中心指向本地、外网请求被关闭。接下来就是验证和排错。

4. 插件装不上的五个经典坑:依赖、兼容、签名与重启玄学

4.1 坑一:插件显示已安装,日志里却是 failed to load

现象:plugins目录里明明放了git.hpi以及相关文件,插件管理页里也能看到这个插件,但 Jenkins 启动日志里有一行Failed to load: ...。

原因:只拷贝了主插件,没拷贝它的依赖链。Jenkins 启动时按顺序解析插件依赖,发现某个依赖插件不存在或者版本过低,直接跳过该插件加载。日志里通常会有明确的依赖缺失信息,类似Dependency of ... is missing。

解决:去资源包doc/目录下的依赖清单里,把报错的插件名在清单里反查,找到对应的.hpi文件补进plugins目录。这里我建议一个动作:不要单独补一两个,而是把资源包plugins/目录下所有文件一次性全部拷入,因为很多插件之间是间接依赖,你手动补完一个又会冒出下一个。全量拷贝虽然换来了目录里「用不上的插件」,但换来的是稳定性和一次通过率,这在交付场景下更划算。

4.2 坑二:在线升级后插件反而不兼容

现象:内网机器之前能联网时装了一批插件,后来网络收紧了。你拿到离线包后,把里面对应的插件文件覆盖进去,重启后报requires Jenkins 2.3xx or higher。

原因:之前在线安装的是当时最新版本,新版本插件的manifest里要求的 Jenkins 核心版本高于 2.346.1。你把离线包里的旧版本覆盖上去之后,如果没清干净残留的文件版本信息,Jenkins 会按新版插件解析,自然报版本不足。

解决:这类问题本质是「新旧版本混装」。我处理时会把涉及报错的插件从plugins目录里彻底删除,连.bak文件也不留,然后重新放入资源包内对应版本。另外,凡是从公网下载过插件的老环境,我会在导入离线包之前先执行一次插件目录全量清理,绝不增量覆盖。增量覆盖是离线部署的雷区,它会让 Jenkins 把新老插件的元数据混在一起。

4.3 坑三:JDK 版本不一致导致构建节点怪病

现象:Jenkins 主程序安装插件正常,但跑流水线时偶尔出现UnsupportedClassVersionError,或者某个需要读取 Java 内部机制的插件直接抛异常。

原因:主节点是 JDK 8,但某个节点的JAVA_HOME指向了 JDK 11,或者反过来。Jenkins 分布式场景下,插件运行在主节点,而构建工具跑在 agent 节点,两边的 JDK 版本不一致就会产生这类时好时坏的怪病。

解决:统一所有节点 JDK 版本,这是最省心的方案。我之前在一个模拟项目里就吃过亏,主节点 JDK 8、某个 agent 上装的 JDK 17,流水线里 maven 编译一切正常,但自定义 Groovy 脚本处理字节码时直接崩。排查了两天才发现是 JDK 版本差异引起的类库行为不一致。从那以后我在每台 agent 上强制执行java -version检测脚本,版本不是 1.8 就直接拒绝登记。

4.4 坑四:更新中心配置后仍然超时

现象:改了hudson.model.UpdateCenter.xml指向本地file://路径,插件管理页还是转圈,日志里能看到它还在尝试访问外网地址。

原因:hudson.model.UpdateCenter.never=true这个系统属性没有生效,或者启动参数里没加。Jenkins 里某些插件自己会请求 Update Center 获取最新版本信息,比如那些带「升级检查」功能的插件,它们走的是另一套网络逻辑,不受更新中心 XML 配置控制。

解决:把-Dhudson.model.UpdateCenter.never=true写进JENKINS_OPTS,并且确认它在java -jar启动命令之前被 export。如果还不行,检查系统环境变量里有没有旧的JENKINS_OPTS覆盖了新值。这个坑的隐蔽之处在于它是「配置看起来对了,但进程没生效」,我一般会在启动脚本第一行加一个env | grep -i jenkins,把所有相关变量打印出来,一眼就能看出参数有没有传进去。

4.5 坑五:重启永远卡在「正在启动」界面

现象:导入离线包后重启 Jenkins,页面一直停留在Jenkins is loading的状态,等十来分钟还是不结束。

原因:某个插件的依赖没满足,Jenkins 在启动阶段反复尝试解析依赖但失败,HTTP 请求一直挂起。很多情况下,这个插件不是你主动装的,而是另一个插件的依赖,它被连带加载后出了问题。

解决:先去$JENKINS_HOME/log/目录翻启动日志,找到卡住的插件名。然后到plugins目录里把它临时移出,再重启一次。如果顺利启动,说明是这个插件的问题,再逐一排查它的依赖。这里给一个排查顺序的习惯:先看报错日志,再动插件目录,最后才考虑是不是内存不足。我见过有人一卡住就加-Xmx堆内存,结果完全没对症,白白浪费半小时。

5. 把插件装好只是开始:从流水线到凭据的落地配置

5.1 全局工具配置:JDK 与构建工具别写到节点里

插件装好只是底子,真正让流水线跑起来还需要在系统配置里把 JDK、构建工具的路径固定下来。很多项目组习惯在各个 agent 节点上手动维护JAVA_HOME,然后流水线里再各自写环境变量,这会造成「同一份 Jenkinsfile,换台机器就构建失败」。正确做法是在 Jenkins 全局工具配置里统一声明,流水线里通过tools块引用。

// 系统管理 → Global Tool Configuration 里配置 JDK 与 Maven env.JAVA_HOME = '/opt/jdk1.8.0_202' def jdkVersion = 'jdk8' def mavenVersion = 'maven-3.8' pipeline { agent any tools { jdk jdkVersion maven mavenVersion } stages { stage('环境信息') { steps { sh 'java -version' sh 'mvn -version' } } } }

这段代码的关键是tools块里的名称要和全局配置里定义的名称严格一致,比如配置 JDK 时填的 name 是jdk8,这里就要写jdk 'jdk8'。名称对不上,流水线会在启动阶段直接报错,而且错误信息比较隐晦。我会在配置完成后立刻跑一段打印版本号的流水线来验证,而不是等实际构建时才发现。

5.2 最小流水线:从 SCM 拉到构建产物

离线环境里装了源码管理插件后,接下来就是一个最小可用的流水线。这个例子覆盖了代码拉取、构建、产物归档三个最基本的环节。

pipeline { agent any tools { jdk 'jdk8' maven 'maven-3.8' } stages { stage('checkout') { steps { checkout([ $class: 'GitSCM', branches: [[name: '*/main']], userRemoteConfigs: [[url: 'http://192.0.2.10/git/demo-project.git']] ]) } } stage('build') { steps { sh 'mvn -B -DskipTests package' } } stage('archive') { steps { archiveArtifacts artifacts: 'target/*.jar', fingerprint: true } } } post { always { junit 'target/surefire-reports/*.xml' } } }

这里的checkout步骤里写的是源码管理插件提供的语法。指纹归档那个参数fingerprint: true建议打开,后续排查「这个 jar 是哪个构建产出的」时非常有用。post块里放测试报告是为了让每次构建结束后自动收集测试结果,即使构建失败也能看到失败原因。这个最小闭环能通,说明源码管理插件、流水线插件、构建工具集成插件配合没问题。

5.3 凭据绑定:让密码只进凭据库

流水线跑通了,下一个要解决的是密码问题。很多初级写法的流水线里会把数据库密码、部署服务器密码直接写在sh命令里,这等于把密码明文写进了 Jenkins 构建历史,谁有查看权限都能看到。正确姿势是用凭据类插件。

pipeline { agent any environment { // 从凭据库读取 SSH 私钥,拉取代码时免密 DEPLOY_KEY = credentials('deploy-key') } stages { stage('deploy') { steps { withCredentials([usernamePassword( credentialsId: 'prod-db-pass', usernameVariable: 'DB_USER', passwordVariable: 'DB_PASS' )]) { sh ''' echo "使用 ${DB_USER} 连接数据库" mysql -u${DB_USER} -p${DB_PASS} -h 192.0.2.20 -e "show databases;" ''' } } } } }

withCredentials里的credentialsId必须和凭据库里录入的 ID 一致,定义prod-db-pass时可以顺手把描述信息写清楚,方便后来接手的人知道这是哪个环境的凭据。另外注意,凭据变量在sh里是通过环境变量引用的,不会出现在日志内容里,Jenkins 会把敏感值自动打码。

5.4 配置文件管理:把 settings.xml 变成版本化文件

最后一个实用配置是配置文件管理。离线环境里最痛苦的是每个 agent 节点的 Mavensettings.xml里的镜像地址、私服地址都要手动改一遍。配置文件管理类插件就是干这个的:把settings.xml上传到 Jenkins 全局配置里,流水线里指定引用,节点构建时自动注入。

pipeline { agent any options { // 指定使用全局配置文件里的 settings configFileProvider( [configFile(fileId: 'maven-global-settings', variable: 'MVN_SETTINGS')] ) { sh 'mvn -s ${MVN_SETTINGS} clean package' } } }

这里的fileId是上传配置文件时生成的唯一标识。好处很明显:私服地址、镜像地址这类环境信息不再散落在各个节点里,而是统一收口到 Jenkins。修改一处,所有流水线立即生效。这类插件看起来不起眼,但在批量交付节点时能把「逐台改文件」的运维工作量直接降为零。

6. 自检脚本与状态验证:全绿才算真的装完

6.1 用 Jenkins 首页接口批量体检

插件装完不等于能用了,我习惯用一段命令做最终体检,确认所有插件都处于enabled和active状态。

# 用 Jenkins API 检查插件加载状态 curl -s "http://127.0.0.1:8080/pluginManager/api/json?depth=1" \ -u admin:admin123 | jq -r ' .plugins[] | select(.enabled==true) | .shortName + " " + .version + " -> " + .active ' # 以 admin 身份登录后,期望输出为每个插件一行,active 都为 true # 示例输出片段: # git 4.13.0 -> true # pipeline 2.26.0 -> true

如果发现某个插件active为false,基本就是依赖缺失或者版本冲突,需要回看第四章的排查路径。jq命令如果没有安装,可以换成 Python 做同样的解析:

curl -s "http://127.0.0.1:8080/pluginManager/api/json?depth=1" \ -u admin:admin123 \ | python3 -c " import json, sys data = json.load(sys.stdin) for p in data['plugins']: if p.get('enabled'): print(p['shortName'], p['version'], '->', p['active']) "

这个检查是离线部署验收里最值得做的事。不能只看插件文件在不在,要看运行时加载状态是不是正常的。

6.2 把插件清单备份下来,形成版本基线

最后一次全绿之后,我会顺手把当前插件清单导出保存,这就是这套环境后续维护的基线:

# 导出当前插件清单到文件,方便后续对比 curl -s "http://127.0.0.1:8080/pluginManager/api/json?depth=1" \ -u admin:admin123 \ | jq -r '.plugins[] | .shortName + ":" + .version' \ | sort > /data/backup/jenkins-plugins-baseline.txt # 下次排查问题时,和这份基线 diff 一下 diff /data/backup/jenkins-plugins-baseline.txt <( \ curl -s "http://127.0.0.1:8080/pluginManager/api/json?depth=1" \ -u admin:admin123 \ | jq -r '.plugins[] | .shortName + ":" + .version' \ | sort \ )

从那以后,我每次在离线环境里交付 Jenkins,都会强制走一遍这个流程:安装完先diff插件清单,再逐项确认active状态,两轮全绿才算真的交付。这套资源本身带了脚本目录,里面就有我上面写的这些检查命令,只是路径和端口要按实际环境改一改。实践下来,最大的收益不是省了多少时间,而是给后续接手的人留下了一台「可以放心操作」的机器,而不是一个黑匣子。希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询