运维|devops|Jenkins Pipeline流程构建
运维|devops|Jenkins Pipeline流程构建 目录1. 运维|devops|Jenkins Pipeline流程构建1.1 Jenkins Pipeline1.1.1 Pipeline script vs Pipeline script from SCM(实操)1.1.2 Jenkinsfile 脚本内容的语法格式如下两种1.2 前置条件1.2.1 服务器端开启ssh登录1.2.2 Jenkinsfile文件和脚本创建1.3 创建Pipeline任务1.3.1 构建相关pipeline1.4 执行构建结果1.5 优化脚本1.5.1 优化脚本之后基于 jenkins Version 2.541.3 实操案例Jenkins Pipeline基于 Groovy 的持续交付流水线代码Pipeline as CodePipeline script vs Pipeline script from SCM(实操)Pipeline script流水线代码直接粘贴在 Jenkins 任务页面文本框内存储在 Jenkins 任务配置数据库中不关联 Git 仓库Pipeline script from SCM流水线代码Jenkinsfile存放在代码仓库 (Git/SVN)Jenkins 运行流水线时先拉取代码读取仓库内的 Jenkinsfile 执行Jenkinsfile 脚本内容的语法格式如下两种Declarative Pipeline声明式-实操语法严格、易读适合绝大多数项目bashpipeline { agent any stages { stage(构建) { steps { echo hello } } } }Scripted Pipeline脚本式原生 Groovy自由度高适合复杂逻辑bashnode { stage(构建) { echo hello } }前置条件git、ssh、jdk、maven 等配置服务器端开启ssh登录生成密钥bashssh-keygen -t rsa -b 4096将公钥添加到本机的 authorized_keysbashcat ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys配置 SSH 服务/etc/ssh/sshd_config)bashPubkeyAuthentication yes PasswordAuthentication yes重启 SSH 服务bashsudo systemctl reload sshd将私钥拷贝到Jenkins全局令牌凭证中Jenkinsfile文件和脚本创建Jenkinsfile位置放入项目pom同级别位置参照baseCore仓库根目录父pom ├─ pom.xml 聚合父工程 ├─ common-core 公共依赖模块无需Jenkinsfile │ └─ pom.xml ├─ Core.Api 业务子模块 │ ├─ pom.xml │ └─ Jenkinsfile ✅ 当前模块流水线文件Groovy构建脚本(Jenkinsfile)bashpipeline { agent any options { disableConcurrentBuilds() timeout(time: 20, unit: MINUTES) timestamps() buildDiscarder(logRotator(numToKeepStr: 10)) } parameters { booleanParam( name: AUTO_DEPLOY, defaultValue: false, description: 构建完成自动推送Jar并重启远程服务 ) } environment { SERVICE_DIR app SERVICE_NAME app JAR_VERSION 1.0.0-SNAPSHOT JAR_FILE ${SERVICE_NAME}-${JAR_VERSION}.jar REMOTE_SUB_DIR ${SERVICE_NAME} REMOTE_FULL_DIR /usr/local/${REMOTE_SUB_DIR} LOCAL_JAR_PATH ${SERVICE_DIR}/target/${JAR_FILE} JAVA_HOME /usr/local/jdk21 M2_HOME /usr/local/maven // SSH 配置 REMOTE_HOST 192.168.0.66 REMOTE_USER test SSH_CREDENTIALS_ID test } stages { stage(1. 环境信息打印) { steps { echo 【构建信息】服务名${env.SERVICE_NAME}Jar包${env.JAR_FILE} echo 本地路径${env.LOCAL_JAR_PATH} echo 远端目录${env.REMOTE_FULL_DIR} } } stage(2. Maven编译打包) { steps { sh test -d ${JAVA_HOME} || { echo ❌ JAVA_HOME目录不存在; exit 1; } test -d ${M2_HOME} || { echo ❌ M2_HOME目录不存在; exit 1; } ${JAVA_HOME}/bin/java -version ${M2_HOME}/bin/mvn -v cd ${SERVICE_DIR} ${M2_HOME}/bin/mvn clean package -DskipTests } } stage(3. 归档构建产物) { steps { archiveArtifacts artifacts: ${env.LOCAL_JAR_PATH}, fingerprint: true, onlyIfSuccessful: true } } stage(4. 远程发布部署) { when { expression { params.AUTO_DEPLOY } } steps { echo 开始推送Jar包并远程重启服务 withCredentials([sshUserPrivateKey( credentialsId: ${env.SSH_CREDENTIALS_ID}, keyFileVariable: SSH_KEY, usernameVariable: SSH_USER )]) { sh set -e -x # 传输 JAR scp -i \$SSH_KEY -o StrictHostKeyCheckingno ${LOCAL_JAR_PATH} ${REMOTE_USER}${REMOTE_HOST}:${REMOTE_FULL_DIR}/${JAR_FILE} # 远程执行部署【修复pgrep匹配BUG】 ssh -i \$SSH_KEY -o StrictHostKeyCheckingno ${REMOTE_USER}${REMOTE_HOST} EOF export JAVA_HOME/usr/local/jdk-21.0.11 SERVICE_NAME${SERVICE_NAME} REMOTE_FULL_DIR${REMOTE_FULL_DIR} JAR_FILE${JAR_FILE} mkdir -p \${REMOTE_FULL_DIR} cd \${REMOTE_FULL_DIR} # 根据服务名杀死进程不再写死jar名称 pkill -f \${SERVICE_NAME} || true sleep 1 # 后台启动服务 nohup \${JAVA_HOME}/bin/java -jar \${JAR_FILE} app.log 21 sleep 3 # 校验进程匹配服务名称不再匹配jar短文件名 if pgrep -f \${SERVICE_NAME} /dev/null; then echo ✅ 服务启动成功 else echo ❌ 服务启动失败打印最近日志 [ -f app.log ] tail -15 app.log || echo app.log 文件尚未生成 exit 1 fi EOF } echo 远程部署流程执行完毕 } } } post { always { echo 【Post钩子】流水线构建结束 } success { cleanWs() echo 流水线全部执行成功 } failure { echo 流水线执行失败请查看日志排查问题 } } }创建Pipeline任务构建相关pipeline脚本指向路径执行构建结果优化脚本增加git 打印、和后台应用日志bashpipeline { agent any options { disableConcurrentBuilds() timeout(time: 20, unit: MINUTES) timestamps() buildDiscarder(logRotator(numToKeepStr: 10)) } parameters { booleanParam( name: AUTO_DEPLOY, defaultValue: false, description: 构建完成自动推送Jar并重启远程服务 ) } environment { SERVICE_DIR app SERVICE_NAME app JAR_VERSION 1.0.0-SNAPSHOT JAR_FILE ${SERVICE_NAME}-${JAR_VERSION}.jar REMOTE_SUB_DIR ${SERVICE_NAME} REMOTE_FULL_DIR /usr/local/${REMOTE_SUB_DIR} LOCAL_JAR_PATH ${SERVICE_DIR}/target/${JAR_FILE} JAVA_HOME /usr/local/jdk21 M2_HOME /usr/local/maven REMOTE_HOST 192.168.0.66 REMOTE_USER test SSH_CREDENTIALS_ID test } stages { stage(1. 环境信息 Git提交日志打印) { steps { sh #!/bin/bash echo Git 最新提交信息 echo 短提交号: $(git rev-parse --short HEAD) echo 完整commit: $(git rev-parse HEAD) echo 提交人姓名: $(git log -1 --pretty%an) echo 提交备注: git log -1 --pretty%B echo echo 【构建信息】服务名${env.SERVICE_NAME}Jar包${env.JAR_FILE} echo 本地路径${env.LOCAL_JAR_PATH} echo 远端目录${env.REMOTE_FULL_DIR} } } stage(2. Maven编译打包) { steps { sh #!/bin/bash test -d ${JAVA_HOME} || { echo ❌ JAVA_HOME目录不存在; exit 1; } test -d ${M2_HOME} || { echo ❌ M2_HOME目录不存在; exit 1; } ${JAVA_HOME}/bin/java -version ${M2_HOME}/bin/mvn -v cd ${SERVICE_DIR} ${M2_HOME}/bin/mvn clean package -DskipTests } } stage(3. 归档构建产物) { steps { archiveArtifacts artifacts: ${env.LOCAL_JAR_PATH}, fingerprint: true, onlyIfSuccessful: true } } stage(4. 远程发布部署) { when { expression { params.AUTO_DEPLOY } } steps { echo 开始推送Jar包并远程重启服务 withCredentials([sshUserPrivateKey( credentialsId: ${env.SSH_CREDENTIALS_ID}, keyFileVariable: SSH_KEY, usernameVariable: SSH_USER )]) { // 使用三双引号 允许Groovy解析Jenkins环境变量 sh #!/bin/bash set -e -x scp -i \$SSH_KEY -o StrictHostKeyCheckingno ${LOCAL_JAR_PATH} ${REMOTE_USER}${REMOTE_HOST}:${REMOTE_FULL_DIR}/${JAR_FILE} ssh -i \$SSH_KEY -o StrictHostKeyCheckingno ${REMOTE_USER}${REMOTE_HOST} EOF SERVICE_NAME${SERVICE_NAME} REMOTE_FULL_DIR${REMOTE_FULL_DIR} JAR_FILE${JAR_FILE} mkdir -p \${REMOTE_FULL_DIR} cd \${REMOTE_FULL_DIR} echo 【1】优雅停止旧服务进程 pgrep -f java.*\${SERVICE_NAME} | xargs kill -15 2/dev/null || true sleep 2 pgrep -f java.*\${SERVICE_NAME} | xargs kill -9 2/dev/null || true sleep 1 echo 【2】启动新服务 追加日志不再清空日志文件 # 远端服务器JAVA路径【硬编码】彻底避开变量冲突大坑 nohup /usr/local/jdk-21.0.11/bin/java -Dfile.encodingUTF-8 -jar \${JAR_FILE} app.log 21 sleep 3 echo 远端应用启动日志尾部30行 [ -f app.log ] tail -30 app.log || echo app.log 文件尚未生成 echo echo 【3】校验进程状态 if pgrep -f java.*\${SERVICE_NAME} /dev/null; then echo ✅ 服务进程启动成功 else echo ❌ 服务启动失败 exit 1 fi EOF } echo 远程部署流程执行完毕 } } } post { always { echo 【Post钩子】流水线构建结束 } success { cleanWs() echo 流水线全部执行成功 } failure { echo 流水线执行失败请查看日志排查问题 } } }优化脚本之后

相关新闻

STM32开发必知:CubeMX沙箱段配置与链接脚本实战解析

STM32开发必知:CubeMX沙箱段配置与链接脚本实战解析

1. 从“沙箱”说起:CubeMX配置的基石逻辑刚接触STM32和CubeMX的朋友,第一次看到“沙箱段”这个词,多半会有点懵。这名字听起来像是某种隔离的安全区域,和芯片配置有什么关系?我第一次在CubeMX的工程设置里看到它时&…

2026/7/31 5:45:00 阅读更多
程序员攻克技术英语:词根词缀实战指南与编程术语解析

程序员攻克技术英语:词根词缀实战指南与编程术语解析

1. 为什么程序员必须啃下词根词缀这块硬骨头“程序员也要学英语”,这话听起来像一句正确的废话,但真正能把它当回事,并且找到高效路径的人,少之又少。很多人一提到学英语,脑子里蹦出来的就是背单词、刷美剧、练口语&am…

2026/7/31 5:45:00 阅读更多
HART协议详解:05 HART现场通信实战

HART协议详解:05 HART现场通信实战

第五季 HART现场通信实战 ——从USB-HART Modem抓包到工程诊断:让协议知识变成维修能力 各位工业现场的工程师朋友们,大家好! 经过前四季的系统学习,我们已经构建了HART协议的完整理论框架: 第一季:六层生命模型与本质认知 第二季:物理层4–20mA与FSK魔法 第三季:数…

2026/7/31 0:14:40 阅读更多
维修工程师的示波器实战:02 探头地线——示波器最大的“坑”

维修工程师的示波器实战:02 探头地线——示波器最大的“坑”

第二篇:探头地线——示波器最大的“坑” ——那根不起眼的小地线,可能比你测的信号还重要 很多工程师第一次用示波器时,都会经历这样一个“惊魂”时刻。 某食品厂包装线,伺服偶发报警。年轻工程师判断是编码器信号受干扰,便拿出示波器认真测量。波形一出来,所有人都倒…

2026/7/31 0:14:40 阅读更多