一、jenkins pipeline简介
1.1、pipeline是什么
Jenkins Pipeline 是 Jenkins 2.0+ 核心的 流水线即代码(Pipeline as Code) 插件套装,用代码(Groovy DSL)定义从代码提交到部署的完整 CI/CD 流程,脚本统一存放在 Jenkinsfile 并纳入 Git/SVN 版本管理【Jenkins Pipeline 是 CI/CD 的 "操作系统",把零散的交付步骤变成可复用、可追溯、可管控的代码化流水线,特别适合中大型项目、微服务、多环境、企业级合规场景,是 DevOps 落地的核心工具】。
简单的说: Pipeline是一套运行在 Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。
Jenkins Pipeline有两种写法【声明式】与【脚本式】:
| 声明式(Declarative)【✅ 首选推荐】 | 脚本式(Scripted) |
|---|---|
| 固定语法、配置化、写流程,像「配置文件」,小白也能看懂,企业 90% 项目首选 | 原生 Groovy 代码、编程化、写逻辑,像「写程序」,适合复杂分支、循环、自定义复杂逻辑 |
* 基于 Jenkins 预定义 DSL 语法,不是纯自由 Groovy * 语法强约束:固定关键字、固定层级结构,写错直接报错 * 设计初衷:标准化、统一流程、降低学习成本、适合团队规范 * 文件后缀:Jenkinsfile 标准写法 |
* 基于 原生 Groovy 脚本,就是在 Jenkins 里跑 Groovy 代码 * 无强制结构:可以随便写 if/else、for 循环、函数、类、异常捕获 * 设计初衷:极致灵活,解决声明式搞不定的复杂业务逻辑 * 早期 Jenkins Pipeline 唯一写法,现在逐步被声明式替代 |
| ✅ 特点: * 结构整齐划一,所有人的流水线长得都差不多 * 不用会 Groovy 编程,照着模板改就行 * 内置:超时、重试、并行、环境变量、post 生命周期,开箱即用 | ✅ 特点: * 完全编程思维:if/else、for、while、函数、类、try-catch 随便用 * 没有强制格式,想怎么写就怎么写 * 老运维 / 开发上手快,但每个人写法都不一样,难以标准化 |
jenkins pipeline的日常使用总结:
- 日常业务、团队标准化、新手入门 → 无脑用 声明式
- 超复杂编程逻辑、动态编排、老项目维护 → 才用 脚本式
- 实际工作:声明式为主,script 内嵌脚本式为辅 是行业通用最佳方案。
1.2、pipeline有啥用
| Pipeline的核心价值 | 说明 |
|---|---|
| 流程代码化、可追溯 | 流水线逻辑写在 Jenkinsfile 里,随代码一起版本控制,可评审、可回滚、可审计,告别 FreeStyle 零散配置Jenkins |
| 全流程自动化(CI/CD 落地) | 一键串联:拉代码 → 编译 / 构建 → 单元测试 → 代码扫描 → 打包 → 镜像构建 → 环境部署 → 冒烟测试 → 生产发布,减少人工干预与错误。 |
| 可视化与可观测 | 阶段视图直观展示各环节状态、耗时、日志;支持失败重试、断点续跑、超时 / 异常处理。 |
| 复杂流程编排能力强 | * 并行执行(如多模块同时构建、多环境并行测试)。 * 条件分支(不同分支 / 环境走不同流程)。 * 人工审批(如生产发布前卡点确认)。 * 跨节点 / 容器调度(Agent 分配、Docker 化构建)。 |
| 复用与标准化 | 支持共享库(Shared Library),通用逻辑封装复用;团队统一 Jenkinsfile 模板,规范交付流程。 |
1.3、pipeline的适用场景
| pipeline的适用场景 | 说明 |
|---|---|
| 标准 CI/CD 流程(最常用) | * 场景:Web 应用、后端服务、移动端、前端项目。 * 流程:代码提交 → 自动构建 → 自动化测试 → 部署到开发 / 测试 / 生产环境。 * 优势:一键发布、质量卡点、全链路追溯。 |
| 微服务 / 多模块项目 | * 场景:几十 / 上百个微服务,依赖复杂、发布频繁。 * 能力:并行构建、依赖编排、批量部署、统一版本管理。 |
| 多环境与复杂发布 | * 场景:开发 → 测试 → 预发 → 生产,多集群 / 多机房部署。 * 能力:环境隔离、配置区分、灰度发布、回滚机制、生产审批卡点。 |
| 基础设施即代码(IaC) | * 场景:K8s 资源编排、Docker 镜像构建、云资源(AWS / 阿里云)创建。 * 能力:与 Kubernetes、Terraform、Ansible 集成,实现环境自动化创建与销毁。 |
| 企业级规范与合规 | * 场景:金融、政企等对流程合规、审计、权限控制要求高。 * 能力:流程固化、操作留痕、审批链、权限分级,满足等保 / 合规审计要求。 |
注意:pipeline不适合【超简单项目(仅单步编译 / 打包,无测试 / 部署)】、【临时一次性任务(用 FreeStyle 更轻量)】。
1.4、pipeline的核心概念
| pipeline的核心概念 | 说明 |
|---|---|
| Node(节点) | 一个 Node 就是一个 Jenkins 节点,Master 或者 Agent,是执行 Step 的具体运行环境。 |
| Stage(阶段) | 一个 Pipeline 可以划分为若干个 Stage,每个 Stage 代表一组操作(如:Build、Test、Deploy,Stage 是一个逻辑分组的概念,可以跨多个 Node) |
| Step(步骤) | Step是最基本的操作单元,可以是打印一句话,也可以是构建一个 Docker 镜像,由各类 Jenkins 插件提供(如命令:sh 'make',就相当于我们平时 shell 终端中执行 make 命令一样)。 |
1.5、pipeline的使用
Pipeline 也有两种创建方法:【可以直接在 Jenkins 的 Web UI 界面中输入脚本】;【也可以通过创建一个 Jenkinsfile 脚本文件放入项目源码库中】。
推荐在 Jenkins 中直接从源代码控制(SCMD)中直接载入 Jenkinsfile Pipeline 这种方法,本文为了更直观的展示,直接在 Web UI 界面中输入脚本。
二、pipeline示例
登录到jenkins的web管理后台,然后点击左上角的【+ 新建Item】输入一个任务名称,然后选择pipeline流水线,然后在【pipeline script】下添加上如下的示例内容即可。
2.1、pipeline的基础示例
bash
node {
stage('Clone') {
echo "1.Clone Stage"
}
stage('Test') {
echo "2.Test Stage"
}
stage('Build') {
echo "3.Build Stage"
}
stage('Deploy') {
echo "4. Deploy Stage"
}
}




2.3、声明式为主+内嵌script内嵌脚本示例
最佳写法规范:
- 95% 流程 用标准声明式结构
- 但凡要循环、遍历、复杂 if、动态逻辑 全部包进
script {} - 绝不单独写老式纯脚本式流水线,维护成本极高
bash
pipeline {
// 运行在任意可用Agent节点
agent any
// 全局环境变量
environment {
// 项目名、版本、仓库地址自行改
PROJECT_NAME = "ops/jpress"
GIT_URL = "git@gitlab2.ck.com:ops/jpress.git"
// 从Jenkins全局配置拿凭证
DOCKER_REGISTRY = "gitlab2.ck.com:5050"
}
// 流水线全局配置
options {
timeout(time: 1, unit: 'HOURS') // 整体流水线1小时超时
buildDiscarder(logRotator(numToKeepStr: '10')) // 只保留最近10条构建记录
retry(count: 1) // 失败自动重试1次
}
// 流水线阶段
stages {
stage('1. 拉取代码') {
steps {
echo "开始拉取代码:${GIT_URL}"
git url: "${GIT_URL}", branch: 'master'
}
}
stage('2. 编译打包') {
steps {
sh '''
export JAVA_HOME=/data/openjdk17
export PATH=$JAVA_HOME/bin:$PATH
/usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true
'''
}
}
stage('3. 代码质量扫描') {
steps {
sh 'mvn sonar:sonar'
}
// 只有master分支才做代码扫描,其他分支跳过
when {
branch 'master'
}
}
stage('4. 复杂自定义逻辑(内嵌Script)') {
steps {
// 声明式里嵌脚本式Groovy,写复杂循环、判断、遍历
script {
// 定义环境列表
def envList = ['dev', 'pre', 'master']
echo "遍历所有待部署环境:"
// 循环遍历
for (env in envList) {
echo "当前处理环境:${env}"
}
// 复杂if-else逻辑
def branchName = env.BRANCH_NAME
if (branchName == 'master') {
echo "主线程:准备预发/生产部署流程"
} else if (branchName.startsWith('feature/')) {
echo "功能分支:只部署开发环境"
} else {
echo "其他分支:仅编译不部署"
}
}
}
}
stage('5. 并行构建多任务') {
steps {
// 声明式原生并行,不用自己写循环
parallel(
"构建镜像": { sh 'docker build -t ${DOCKER_REGISTRY}/${PROJECT_NAME}:${BUILD_NUMBER} .' },
"推送镜像": { sh 'docker push ${DOCKER_REGISTRY}/${PROJECT_NAME}:${BUILD_NUMBER}' }
)
}
}
stage('6. 部署到开发环境') {
when {
branch 'master'
}
steps {
sh 'echo 执行K8s/服务器部署命令...'
}
}
stage('7. 生产发布人工审批') {
when {
branch 'master'
}
steps {
// 人工卡点确认,不点不往下走
input message: '确认是否发布到生产环境?', ok: '确认发布'
sh 'echo 执行生产发布...'
}
}
}
// 流水线后置处理:不管成功失败都执行
post {
success {
echo "✅ 流水线构建部署成功"
// 可加钉钉/企业微信/邮件通知脚本
}
failure {
echo "❌ 流水线执行失败,请查看日志排查"
}
always {
echo "🔔 本次构建编号:${BUILD_NUMBER},构建地址:${BUILD_URL}"
cleanWs() // 每次跑完清空工作空间,防止磁盘爆满
}
}
}
2.3、pipeline实现部署jpress
注意:【scp 指定端口是大写的P】【ssh指定端口是小写的p】
《1》scp -P 22222 本地文件 root@192.168.1.30:/远程路径
《2》ssh -p 22222 root@192.168.1.30:/远程路径 ./本地路径
bash
pipeline {
agent any
// 定义全局变量,避免重复写
environment {
REMOTE_HOST = '192.168.1.30'
REMOTE_USER = 'root'
REMOTE_PORT = '22222'
REMOTE_DIR = '/usr/local/jpsweb'
WORKSPACE = '/data/jenkins/work2'
}
stages {
stage('git clone code & build') {
steps {
ws(dir: "${WORKSPACE}") {
git(url: 'git@gitlab2.ck.com:ops/jpress.git', branch: 'master')
sh '''
export JAVA_HOME=/data/openjdk17
export PATH=$JAVA_HOME/bin:$PATH
/usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true
'''
}
}
}
stage('Copy to Remote Host') {
steps {
ws(dir: "${WORKSPACE}") {
script {
// 远程执行脚本
def shellScript = """
#!/bin/bash
ssh -p ${REMOTE_PORT} ${REMOTE_USER}@${REMOTE_HOST} 'rm -rf ${REMOTE_DIR} && mkdir -p ${REMOTE_DIR}'
scp -P ${REMOTE_PORT} starter/target/starter-4.0.zip ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/
scp -P ${REMOTE_PORT} start-jpress1.sh ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/
ssh -p ${REMOTE_PORT} ${REMOTE_USER}@${REMOTE_HOST} "cd ${REMOTE_DIR} && unzip -o starter-4.0.zip"
"""
writeFile file: 'remote_deploy.sh', text: shellScript
}
}
}
}
stage('Execute Remote Script') {
steps {
ws(dir: "${WORKSPACE}") {
sh 'chmod +x remote_deploy.sh'
sh './remote_deploy.sh'
}
}
}
stage('Start Service') {
steps {
script {
// 后台启动必须用 nohup,否则 Jenkins 断开连接服务会被杀掉
sh """
ssh -p ${REMOTE_PORT} ${REMOTE_USER}@${REMOTE_HOST} \\
"cd ${REMOTE_DIR} && chmod 755 start-jpress1.sh && nohup ./start-jpress1.sh > /dev/null 2>&1 &"
"""
}
}
}
}
}





