📌 前言

在企业级开发中,我们常常面临 新老项目并存 的复杂局面:

老项目基于 JDK 8 开发,短期内无法升级;
新项目采用 JDK 17(LTS)甚至更高版本;
而作为 CI/CD 核心的 Jenkins,官方推荐使用 JDK 11+,最新版本更建议使用 JDK 17 或 JDK 21 以获得最佳性能和安全性。
如何在一个环境中统一管理多个 JDK 版本,让 Jenkins 自身运行在现代 JDK 上,同时又能灵活构建不同 JDK 版本的项目?

本文将带你从零开始,完成:

✅ 安装 JDK8、JDK17、JDK21

✅ 使用 JDK21 部署 Jenkins(WAR 方式)

✅ 配置 Jenkins 支持多版本 JDK 构建任务

✅ 实际验证不同 JDK 项目的自动化构建

1. 安装JDK

(1) 下载JDK并且解压到指定路径,如图是解压后的路径
在这里插入图片描述
(2)修改/etc/profile,添加以下内容

JAVA_HOME=/usr/local/java/jdk1.8.0_212
JRE_HOME=/usr/local/java/jdk1.8.0_212/jre
CLASS_PATH=:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/binalias java8='export JAVA_HOME=/usr/local/java/jdk1.8.0_212 && export CLASSPATH=.:${JAVA_HOME}/lib && export PATH=${JAVA_HOME}/bin:$PATH && java -version'
alias java17='export JAVA_HOME=/usr/local/java/jdk17 && export CLASSPATH=.:${JAVA_HOME}/lib && export PATH=${JAVA_HOME}/bin:$PATH && java -version'
alias java21='export JAVA_HOME=/usr/local/java/jdk21 && export CLASSPATH=.:${JAVA_HOME}/lib && export PATH=${JAVA_HOME}/bin:$PATH && java -version'

然后执行 source /etc/profile
然后输入java8,java17,java21,可以切换到指定版本的jdk
在这里插入图片描述

2. 安装jenkins

(1)下载jenkins war包
https://www.jenkins.io/doc/book/installing/war-file/
在这里插入图片描述
(2)上传war包,并且启动
在启动jenkins之前,需要安装字体,否则启动失败

## 安装字体
sudo yum install -y fontconfig
sudo yum install -y liberation-fonts
## 切换到jdk21
java21
## 指定自定义端口8888
nohup java -jar jenkins.war --logfile=/opt/jenkins/jenkins.log --httpPort=8888 &

(3) 设置账号,以下均为截图
浏览器输入ip:8888 ,获取管理员密码,然后进入开始设置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
点击开始使用jenkins,到此已经算安装成功
(4)安装插件
在这里插入图片描述
安装插件(我们需要实现拉取代码,打包,部署(单节点,跨节点))
Localization: Chinese (Simplified)
Maven Integration
Publish Over SSH
SSH Build Agents
SSH Agent
Pipeline
Git client
Git
安装完成后重启,可以在浏览器输入:ip:8888/restart
(5) jenkins 机器安装插件
(a)安装maven
修改/etc/profile

export MAVEN_HOME=/usr/local/maven
export PATH=${MAVEN_HOME}/bin:${PATH}

source /etc/profile

(b)安装git
yum install git
说明:在这块安装了maven和git就是让服务器去操作打包和拉取代码的事情,不让jenkins去操作打包(可能有矛盾,jenkins让打包,其实打包还是在服务器上)
(6)凭据管理
在这块输入服务器的账密和git的私钥
在这里插入图片描述
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e2a1c957326f49a8863257b389012cca.png

这里面的ID就是唯一值,后面在节点管理或者Pipeline代码块用

(7)节点管理
在这里插入图片描述
在这里插入图片描述
(8) 创建作业

pipeline {agent noneenvironment {// Git 仓库GIT_REPO = 'ssh://git@ip:10022/admin/xgov-agent.git'// 本地构建路径(在 Jenkins Master 上)WORKSPACE = "${APP_DIR}/workspace"BUILD_JAR_DIR = "${WORKSPACE}/jars"DEPLOY_DIR = "${APP_DIR}/app"TARGET_ZIP  = "${APP_NAME}.zip"// yeexun170 部署配置NODE_DEPLOY_USER     = 'root'           // yeexun170 上的用户名NODE_DEPLOY_HOST     = '172.32.1.170'             // 主机名或 IPNODE_DEPLOY_DIR      = "/opt/apps/${APP_NAME}"  // yeexun170 上的部署目录// Java 启动参数JAVA_OPTS       = '-Xms512m -Xmx1024m'START_JAR       = "${APP_NAME}.jar"}stages {stage('准备目录') {agent {label 'master'}steps {script {echo "📁 准备本地构建目录"}sh """rm -rf ${WORKSPACE}/* .gitmkdir -p ${WORKSPACE}echo "✅ 目录已清理""""}}stage('拉取代码') {agent {label 'master'}steps {script {echo "🔧 拉取代码:${GIT_REPO} 分支:${BRANCH}"}checkout changelog: false, scm: [$class: 'GitSCM',branches: [[name: '${BRANCH}']],doGenerateSubmoduleConfigurations: false,extensions: [[$class: 'CloneOption', depth: 1, noTags: false, reference: '', shallow: true, timeout: 30]],submoduleCfg: [],userRemoteConfigs: [[credentialsId: '001', url: 'ssh://git@172.32.1.6:10022/admin/xgov-agent.git']]]}}stage('Maven 打包') {agent {label 'master'}steps {script {echo "📦 使用 Maven 打包(Java 17)..."}sh """# jenkins 把代码拉取到这个位置cd /root/.jenkins/workspace/test_node# 加载环境source /etc/profile || true# 切换 Java 17(根据实际路径调整)java17java -versionif [ ! -f pom.xml ]; thenecho "❌ 未找到 pom.xml"exit 1fimvn clean install -DskipTestsif [ \$? -ne 0 ]; thenecho "❌ Maven 构建失败"exit 1fi"""}}stage('创建传输路径') {agent {label 'yeexun170'}steps {script {echo "🚚 创建路径"}sh """mkdir -p ${NODE_DEPLOY_DIR}echo "路径创建成功""""}}stage('SCP 上传到 yeexun170') {agent {label 'master'}steps {script {echo "🚚 正在上传到 /root/.jenkins/workspace/test_node/jars:${NODE_DEPLOY_DIR}"}sh """scp /root/.jenkins/workspace/test_node/jars/${TARGET_ZIP} ${NODE_DEPLOY_USER}@${NODE_DEPLOY_HOST}:${NODE_DEPLOY_DIR}/if [ \$? -eq 0 ]; thenecho "✅ 文件已上传到 yeexun170"elseecho "❌ SCP 上传失败,请检查 SSH 连接"exit 1fi"""}}stage('在 yeexun170 上部署并启动') {agent {label 'yeexun170'}steps {script {echo "🚀 在 yeexun170 上部署并启动服务"}sh """# 加载环境source /etc/profile || true# 切换 Java 17(根据实际路径调整)java17java -versionecho "📦 准备新版本文件..."
cd ${NODE_DEPLOY_DIR}# 1. 备份旧版本(如果存在)if [ -d ${APP_NAME} ]; thenecho '📁 备份旧版本'rm -rf ${APP_NAME}_oldmv ${APP_NAME} ${APP_NAME}_oldfi# 2. 解压新版本到临时目录if [ ! -f ${TARGET_ZIP} ]; thenecho '❌ 错误:未找到更新包 ${TARGET_ZIP}'exit 1fiecho '📦 解压新版本...'unzip ${TARGET_ZIP}if [ \$? -ne 0 ]; thenecho '❌ 解压失败,恢复旧版本'[ -d ${APP_NAME}_old ] && mv ${APP_NAME}_old ${APP_NAME}exit 1fi# 4. 停止旧服务(最后才停)PID=\$(ps aux | grep '${START_JAR}' | grep -v 'grep' | awk '{print \$2}')if [ -n \"\$PID\" ]; thenecho \"🛑 停止旧服务 PID: \$PID\"kill -15 \$PIDsleep 8if ps -p \$PID > /dev/null 2>&1; thenkill -9 \$PIDecho \"✅ 强制终止\"fifi# 5. 启动新服务echo '🚀 启动新服务...'cd ${NODE_DEPLOY_DIR }/${APP_NAME}JENKINS_NODE_COOKIE=dontKillMe nohup java \${JAVA_OPTS} -jar ${START_JAR} > app.log 2>&1 &# 6. 检查是否启动成功sleep 10if pgrep -f \"java.*${APP_NAME}\" > /dev/null; thenecho '✅ 服务已启动'elseecho '❌ 启动失败,请检查日志'tail -n 30 app.logexit 1fi"""}}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94758.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94758.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/94758.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Autodesk Maya 2026.2 全新功能详解:MotionMaker AI 动画、LookdevX 材质增强、USD 工作流优化

软件介绍 Autodesk Maya 2026.2是一款专业的3D计算机图形软件,它为数字内容创作者提供了丰富的工具集,以实现高质量的建模、动画、模拟和渲染。该版本带来了多项性能优化和工作流程改进,特别是针对生成式动画工具MotionMaker进行了重大升级&…

STM32之DMA详解

一、DMA 1. DMA的引入 在嵌入式系统或计算机系统中,数据的传输和处理是非常重要的操作。以下通过一个简单的示例来展示传统数据操作方式与 DMA 引入的必要性: int a 10; int b 20;a b;上述代码包含了变量定义、初始化以及变量数据赋值操作。在传统…

链表有环找入口节点原理

环形链表入口检测算法数学解释 数学原理假设定义: 链表头到环入口的距离为 a环入口到相遇点的距离为 b相遇点到环入口的距离为 c环的长度为 b c第一次相遇时: 慢指针走了 s a b 步快指针走了 f a b n(b c) 步,其中 n 是快指针在环内转的圈数由于快指针速度是…

Java 基本类型与包装类详解

Java 基本类型与包装类详解 在 Java 开发中,理解 基本数据类型与包装类、字符串处理、以及高精度计算类是非常核心的能力。这不仅关系到程序性能,还影响代码的正确性和可维护性。本文将详细讲解这些知识点,并给出常见的使用技巧和陷阱。 1️…

CRYPT32!CryptMsgUpdate函数分析之CRYPT32!PkiAsn1Decode函数的作用是得到pci

第一部分: CryptMsgUpdate( #endifIN HCRYPTMSG hCryptMsg,IN const BYTE *pbData,IN DWORD cbData,IN BOOL fFinal) {ContentInfo *pci NULL;if ((PHASE_FIRST_FINAL pcmi->dwPhase) &&(0 pcmi->dwMsgType)) {if (0 …

华为交换机S5700设置acl

1.、配置ACL1.1、定义允许的ACL规则[sw1]acl number 3001[sw1-acl-adv-3001]rule permit ip source 192.168.20.0 0.0.0.255 destination 192.168.40.1 0[sw1-acl-adv-3001]rule permit ip source 192.168.30.0 0.0.0.255 destination 192.168.40.1 01.2、定义禁止的ACL规则[sw…

在使用spring ai进行llm处理的rag的时候,选择milvus还是neo4j呢?

在使用spring ai进行llm处理的rag的时候,选择milvus还是neo4j呢? 对于Spring AI中的RAG(Retrieval-Augmented Generation)应用,选择Milvus还是Neo4j,主要取决于你的数据类型以及RAG流程中对数据检索的侧重点…

计算机视觉与深度学习 | 视觉里程计技术全景解析:从原理到前沿应用

视觉里程计技术全景解析:从原理到前沿应用 一、定义与核心价值 二、技术原理与分类体系 2.1 基本工作流程 2.2 主流技术路线对比 2.3 算法范式演进 三、典型应用场景 3.1 地面移动机器人 3.2 自动驾驶领域 3.3 深空探测 3.4 增强现实 四、核心技术挑战与突破路径 4.1 主要技术…

Wireshark和USRP捕获同一信号波形差异原因

一、波形差异 在前面的博客中我对比绘制了同一信号的Wireshark和USRP两种波形: 可以看出波形差别还是挺大的,尤其是在信号分布间隔方面。 我猜想Wireshark的一条数据包在物理上并不是连续的: 而是分组发送,但在Wireshark中合并在…

Python-GEE遥感云大数据分析、可视化与Satellite Embedding应用

随着航空、航天、近地空间遥感平台的持续发展,遥感技术近年来取得显著进步。遥感数据的空间、时间、光谱分辨率及数据量均大幅提升,呈现出大数据特征。2025年7月,Google DeepMind发布了革命性的AlphaEarth Foundations模型及Satellite Embedd…

Python常见设计模式2: 结构型模式

文章目录适配器模式桥接模式组合模式外观模式代理模式适配器模式 将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。两种实现方式: 类适配器:使用多继承对象适配器:使用组合…

HDMI2.1 8K验证平台

本文推荐其中一个平台ZCU106HDMI2.1 FMC Card 一、ZCU106主要特性与优势 经过优化,可采用 Zynq Ultrascale MPSoC 快速进行应用原型设计集成型视频编解码器单元支持 H.264/H.265HDMI 视频输入输出PCIe 端点 Gen3x4、USB3、DisplayPort 和 SATADDR4 SODIMM – 64 位…

R语言使用随机森林对数据进行插补

数据插补的目的是为了恢复数据的完整性,以便后续的数据分析和挖掘工作能够顺利进行。插补方法的选择取决于数据的特点和缺失模式。常见的插补方法包括均值插补、回归插补、多重插补等。均值插补简单易行,但可能会改变数据分布;回归插补考虑了…

论文阅读:ICLR 2024 GAIA: A Benchmark for General AI Assistants

https://arxiv.org/pdf/2311.12983 https://www.doubao.com/chat/18484357054754562 GAIA: A Benchmark for General AI Assistants GAIA:通用人工智能助手基准测试 该论文介绍了GAIA(General AI Assistants)基准测试,这是一…

【Cmake】静态库(编译-链接-引用)相关函数

目录 一.file 1.1.示例一 1.2.示例二 1.2.1.GLOB 1.2.2.GLOB_RECURSE 1.3.示例三 1.3.1.GLOB 1.3.2.GLOB_RECURSE 1.4.file(GLOB)的缺点 二.add_library 示例 1:创建一个简单的静态库 示例 2:创建一个简单的共享库(动态库&#x…

【50页PPT】钢铁企业数字化工厂解决方案需求要点(附下载方式)

篇幅所限,本文只提供部分资料内容,完整资料请看下面链接 https://download.csdn.net/download/2501_92796370/91716817 资料解读:钢铁企业数字化工厂解决方案需求要点 详细资料请看本解读文章的最后内容 钢铁行业数字化转型背景与意义 当…

Java深拷贝与浅拷贝核心解析

Java深拷贝与浅拷贝的概念浅拷贝(Shallow Copy)只复制对象的引用,而不复制对象本身。拷贝后的对象和原对象共享同一块内存地址中的子对象。修改其中一个对象的非基本类型属性时,另一个对象的对应属性也会被修改。深拷贝&#xff0…

DBeaver 的 PostgreSQL 驱动包默认存储位置

在 Windows 系统中,DBeaver 的 PostgreSQL 驱动包(JDBC 驱动 JAR 文件)默认存储位置如下: ###🔍 默认驱动安装路径 C:\Users\你的用户名\AppData\Roaming\DBeaverData\drivers说明:你的用户名:…

大数据毕业设计选题推荐:基于北京市医保药品数据分析系统,Hadoop+Spark技术详解

🍊作者:计算机毕设匠心工作室 🍊简介:毕业后就一直专业从事计算机软件程序开发,至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长:按照需求定制化开发项目…

Package.xml的字段说明

package.xml 的版本说明 <package format"2"></package>每一个 package.xml 都以作为 root 标签&#xff0c;其中 format 代表版本,现在主要是版本 2 为主,与版本 1 之间的差别主要是一些子标签, package.xml 的必备标签 name:功能包名 version:版本号。…