运维|devops|JenkinsPipeline流程构建
运维|devops|Jenkins Pipeline流程构建基于 jenkins Version 2.541.3 实操案例Jenkins Pipeline基于 Groovy 的持续交付流水线代码(Pipeline as Code)Pipeline script vs Pipeline script
运维|devops|Jenkins Pipeline流程构建
基于 jenkins Version 2.541.3 实操案例Jenkins Pipeline
基于 Groovy 的持续交付流水线代码(Pipeline as Code)Pipeline script vs Pipeline script from SCM(实操)
Pipeline script
流水线代码直接粘贴在 Jenkins 任务页面文本框内,存储在 Jenkins 任务配置数据库中,不关联 Git 仓库Pipeline script from SCM
流水线代码(Jenkinsfile)存放在代码仓库 (Git/SVN),Jenkins 运行流水线时先拉取代码,读取仓库内的 Jenkinsfile 执行
Jenkinsfile 脚本内容的语法格式如下两种
Declarative Pipeline(声明式-实操)这套写法,语法更严格,结构也更清晰,读起来一目了然,放到绝大多数项目里都很合适。
pipeline {
agent any
stages {
stage('构建') {
steps {
echo "hello"
}
}
}
}Scripted Pipeline(脚本式):基于原生 Groovy 编写,自由度很高,尤其适合处理复杂逻辑。
node {
stage('构建') {
echo "hello"
}
}
前置条件
git、ssh、jdk、ma ven 等配置服务器端开启ssh登录
生成密钥
ssh-keygen -t rsa -b 4096将公钥添加到本机的 authorized_keys
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys配置 SSH 服务(/etc/ssh/sshd_config)
PubkeyAuthentication yes
PasswordAuthentication yes重启 SSH 服务
sudo systemctl reload sshd- 将私钥拷贝到Jenkins全局令牌凭证中

Jenkinsfile文件和脚本创建
Jenkinsfile位置放入项目pom同级别位置参照
Core(仓库根目录|父pom)
├─ pom.xml 聚合父工程
├─ common-core 公共依赖模块(无需Jenkinsfile)
│ └─ pom.xml
├─ Core.Api 业务子模块
│ ├─ pom.xml
│ └─ Jenkinsfile 当前模块流水线文件Groovy构建脚本(Jenkinsfile)
pipeline {
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}"
JA VA_HOME = '/usr/local/jdk21'
M2_HOME = '/usr/local/ma ven'
// 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. Ma ven编译打包') {
steps {
sh '''
test -d ${JA VA_HOME} || { echo " JA VA_HOME目录不存在"; exit 1; }
test -d ${M2_HOME} || { echo " M2_HOME目录不存在"; exit 1; }
${JA VA_HOME}/bin/ja va -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 StrictHostKeyChecking=no ${LOCAL_JAR_PATH} ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_FULL_DIR}/${JAR_FILE}
# 远程执行部署【修复pgrep匹配BUG】
ssh -i $SSH_KEY -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_HOST} << 'EOF'
export JA VA_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 ${JA VA_HOME}/bin/ja va -jar ${JAR_FILE} > app.log 2>&1 &
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 打印、和后台应用日志pipeline {
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}"
JA VA_HOME = '/usr/local/jdk21'
M2_HOME = '/usr/local/ma ven'
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. Ma ven编译打包') {
steps {
sh '''#!/bin/bash
test -d ${JA VA_HOME} || { echo " JA VA_HOME目录不存在"; exit 1; }
test -d ${M2_HOME} || { echo " M2_HOME目录不存在"; exit 1; }
${JA VA_HOME}/bin/ja va -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 StrictHostKeyChecking=no ${LOCAL_JAR_PATH} ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_FULL_DIR}/${JAR_FILE}
ssh -i $SSH_KEY -o StrictHostKeyChecking=no ${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 "ja va.*${SERVICE_NAME}" | xargs kill -15 2>/dev/null || true
sleep 2
pgrep -f "ja va.*${SERVICE_NAME}" | xargs kill -9 2>/dev/null || true
sleep 1
echo "【2】启动新服务 >> 追加日志,不再清空日志文件"
# 远端服务器JA VA路径【硬编码】,彻底避开变量冲突大坑
nohup /usr/local/jdk-21.0.11/bin/ja va -Dfile.encoding=UTF-8 -jar ${JAR_FILE} >> app.log 2>&1 &
sleep 3
echo "========== 远端应用启动日志(尾部30行) =========="
[ -f app.log ] && tail -30 app.log || echo "app.log 文件尚未生成"
echo "===================================================="
echo "【3】校验进程状态"
if pgrep -f "ja va.*${SERVICE_NAME}" > /dev/null; then
echo " 服务进程启动成功"
else
echo " 服务启动失败!"
exit 1
fi
EOF
"""
}
echo "远程部署流程执行完毕"
}
}
}
post {
always {
echo "【Post钩子】流水线构建结束"
}
success {
cleanWs()
echo " 流水线全部执行成功!"
}
failure {
echo " 流水线执行失败,请查看日志排查问题!"
}
}
}优化脚本之后


Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。
赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。
Blender 是一款免费开源、跨平台的专业 3D 创作软件,集建模、动画、渲染、视频编辑与视觉合成等功能于一体,广泛应用于影视动画、游戏设计和建筑可视化等领域。软件支持 Cycles 物理渲染器与 Eevee 实时渲染引擎,并提供多边形建模、骨骼绑定、物理模拟等专业工具。Blender 兼容 Windows、macOS 和 Linux 系统,安装包轻巧、运行流畅,依托活跃的全球开发者社区持续更新,是从初学者到专业创作者都值得选择的正版 3D 创作工具。
Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。
极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。














