❗️ 友情提示:本篇前半部分理论性内容较多,可以直接从[声明式]部分看,再回来看理论部分
简介
什么是 Jenkins
Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建、测试和部署软件。 Jenkins 支持各种运行方式,可通过系统包、Docker 或者通过一个独立的 Java 程序。
什么是 Pipeline
Jenkins Pipeline(或简称为 “Pipeline”,或称为"Jenkins 流水线")是一套插件,它支持实现和集成
continuous delivery pipelines到 Jenkins。
是一套运行于Jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化。
Pipeline是Jenkins2.X的最核心的特性,帮助Jenkins实现从CI到CD与DevOps的转变。
对Jenkins 流水线的定义被写在一个文本文件中 (Jenkinsfile),该文件可以被提交到项目中,一般在根目录。
下面会详细介绍 Pipeline 的语法。
入门
安装jenkins
- 下载 Jenkins;
- 打开终端进入到下载目录;
- 运行命令 java -jar jenkins.war --httpPort=8080;
- 打开浏览器进入链接 http://localhost:8080;
- 按照页面说明完成安装。
第 5 步会提示你需要安装一些插件,建议全部安装,这里依赖下载所用时间和网络环境有关,如果失败了可以重新下载,或者先选择跳过,进入到Jenkins页面的时候还可以重新安装。
创建 Pipeline
⚠️注意:这里使用的是 Jenkins经典UI 界面(默认的),使用 Blue Ocean UI 界面的可以去官网查阅。
- 进入jenkins页面,单击Jenkins左侧菜单中的
New Item(汉化的叫新建 Item) 菜单; - 随便起一个名字,选择 Pipeline(汉化的叫
流水线),点击Save(汉化的叫确定);
这时候你已经创建了一个Pipeline的Item,但是还没有写 Pipeline 脚本,在打开的页面中,往下找,找到 流水线 部分。
Pipeline脚本来源有两个地方:
- 默认
定义选的是Pipeline script,下方有一个文本域,这里可以直接写Pipeline脚本。 - 点击
定义选项,选择Pipeline script from SCM,SCM选Git,在新增的信息项里填写git地址、选择一个用户(没有的话点add添加).
填写完信息后点save(保存),回到你创建的这个item中,点击左侧菜单的“Build Now(立即构建)”就可以执行Pipeline脚本了。
第2种可以看到脚本路径的值默认是Jenkinsfile,意思就是默认取当前git仓库根目录下的Jenkinsfile文件,这个文件里写Pipeline脚本,内容和第一种的一样。
第2种用法,把Pipeline内容写到Jenkinsfile里,Jenkinsfile在项目源码中维护,是官方推荐的,这种方式可以达到Pipeline as Code(流水线即代码)的目的。
将 CD 流水线作为应用程序的一部分,像其他代码一样进行版本化和审查。 创建
Jenkinsfile并提交它到源代码控制中提供了一些即时的好处:
- 自动地为所有分支创建流水线构建过程并拉取请求。
- 在流水线上代码复查/迭代 (以及剩余的源代码)。
- 对流水线进行审计跟踪。该流水线的真正的源代码, 可以被项目的多个成员查看和编辑。
但是这种设定也会有令人头疼的时候,比如我们团队的项目,微服务有几十个,每个服务都有自己的Jenkinsfile,而内容都基本一样,有个小改动就需要通知所有负责人一起修改。
这时候就需要想办法怎么样可以统一管理Jenkinsfile。(这个问题等实践了解决后后续会发新博文)
Pipeline语法
流水线语法分为两种:声明式和脚本式。
- 两种都是 DSL 语言(domain-specific language)
- 声明式流水线的是 Jenkins 流水线更近的特性:
- 相比脚本化的流水线语法,它提供更丰富的语法特性,
- 是为了使编写和读取流水线代码更容易而设计的。
但是真正在项目中用的时候,往往是两种语法混用,以解决特殊需求。
一、脚本式(scripted-pipeline)
脚本式流水线是一种基于 Groovy 的领域特定语言,大多数 Groovy 语法都可以无需修改,直接在脚本式流水线中使用。
本篇主要使用声明式,感兴趣的可以自行查阅Groovy相关知识点。
二、声明式(declarative-pipeline)
声明式流水线是2.5版本添加到 Jenkins 流水线的,它在流水线子系统之上提供了一种更简单,更有主见的语法。下面是一个最基础的例子:
pipeline {
agent any
stages {
stage('Stage 1') {
steps {
echo 'Hello world!'
}
}
}
}2
3
4
5
6
7
8
9
10
可以直接在UI界面的Pipeline面板中编写:

也可以写在项目中的Jenkinsfile文件中。
写完点保存,回到这个流水线项目的页面:
- 点击左侧“Build now”(立即构建);
- 页面左侧
Build History中会出现一条新记录; - 等待构建成功(相信你自己能看出来怎么算成功);
- 点击第
Build History中的#1(你构建了两次,那就是#2); - 点击 Console Output 来查看流水线运行的全部输出

声明式语法
所有有效的声明式流水线必须包含在一个 pipeline 块中, 比如:
pipeline {
/* insert Declarative Pipeline here */
}2
3
块只能由:节段(Sections)、指令(Directives)、步骤(Steps)、 或赋值语句(assignment statements)组成。
Sections
节段通常包含一个或多个指令或步骤
由四个 section 构成:agent、post、stages、steps。
比如下面例子中的 agent 部分就属于一个 section,stages 部分也属于一个 section:
pipeline {
agent any
stages {
...
}
}2
3
4
5
6
这四个 section 在官方文档里有详细解释:section - 官方文档,这里简单解释一下:
agent - 可以简单理解为指定Jenkins的运行环境;
post - 可以理解为Jenkins运行结束时的钩子或ajax的回调;
stages - 由多个阶段(stage)构成,主要代码都运行在stage里,把构建脚本按大的步骤执行;
steps - 一个stage由多个steps构成,把构建脚本某一步骤再细分小步骤;
Directives
指令包含:environment、options、parameters、triggers、Jenkins cron syntax、stage、tools、input、when
解释几个常用的:
1、environment
环境变量,可以设置全局环境变量或者局部环境变量,方便管理一些经常要改的数据
Jenkins 流水线通过全局变量 env 提供环境变量,它在 Jenkinsfile 文件的任何地方都可以使用
pipeline {
agent any
environment {
USERNAME_V = 'Vinsea'
}
stages {
stage('第一步') {
environment {
AN_ACCESS_KEY = '111222333444555666'
}
steps {
sh 'printenv'
}
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 顶层流水线块中使用的 environment 指令将适用于流水线中的所有步骤。
- 也就是 USERNAME_V 将可以在整个流水线中被调用* 在一个 stage 中定义的 environment 指令只会将给定的环境变量应用于 stage 中的步骤。
- 也就是 AN_ACCESS_KEY 只能在 “第一步” 这个stage中被调用
⚠️ 怎么调用呢?这里是一个比较容易踩到的坑
- 普通调用,通过
env变量:env.USERNAME_V - 在
sh单行(一对儿单引号)脚本中调用:$USERNAME_V - 在
sh多行(一对儿三单/双引号)脚本中调用:${USERNAME_V} - 在字符串中调用:
${USERNAME_V}或者${env.USERNAME_V},类似 ES6 模板字符串的风格
⚠ Jenkins pipeline的单引号、双引号和转义字符的语法和Linux shell中的语法类似:
- 在单引号之间的所有特殊字符都失去了特殊含义,除了以下特例:
- 在 shell 中调用变量* 在双引号之间的绝大多数特殊字符都失去了特殊含义,除了以下特例:
- $ 美元号用来提取变量的值
- ` 反冒号用执行命令
- \ 反斜杠用来转义字符
pipeline {
agent any
environment {
USERNAME_V = 'Vinsea'
}
stages {
stage('第一步') {
environment {
AN_ACCESS_KEY = '111222333444555666'
}
steps {
sh 'printenv'
echo 'My name is $USERNAME_V' // 输出 My name is ${USERNAME_V}
echo 'My name is ${USERNAME_V}' // 输出 My name is ${USERNAME_V}
echo "My name is ${USERNAME_V}" // 输出 My name is Vinsea
echo "My name is ${env.USERNAME_V}" // 输出 My name is Vinsea
echo env.USERNAME_V // 输出 Vinsea
sh 'echo $env.USERNAME_V' // 输出 .USERNAME_V
sh 'echo env.USERNAME_V' // 输出 env.USERNAME_V
sh 'echo $USERNAME_V' // 输出 Vinsea
sh '''
echo ${USERNAME_V} // 输出 Vinsea
'''
}
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
pipeline自带一些全局环境变量,可以在自己搭建的 Jenkins 里查询到:
YOUR_JENKINS_URL/pipeline-syntax/globals#env用法和上面一样。
2、input
stage 的 input 指令允许你使用 input step 提示输入,可以在构建的过程中停止构建,等用户输入内容时才能继续
pipeline {
agent any
stages {
stage('Example') {
input {
message "确定要继续吗?"
ok "确定!"
submitter "Vinsea,admin" // 只有 Vinsea账户和admin账户可以提交
parameters {
string(name: 'PERSON', defaultValue: 'Mr Vinsea', description: '你叫啥?')
}
}
steps {
echo "你好, ${PERSON}." // 获取输入框内容的参数
}
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18