10分钟搞定让你困惑的 Jenkins 环境变量
前言
Jenkins, DevOps 技术栈的核心之一,CI/CD 离不开编写 Pipeline 脚本,上手 Jenkins ,简单查一下文档,你就应该不会被 agent,stages,step 这类关键词弄懵,也能很快构建出 pipeline 的骨架
但是当向骨架中填充内容的时候,尤其如何利用环境变量(系统内置 | 自定义),多数人都会变得比较混乱,浪费很多时间,本文就帮助大家快速通关环境变量

准备
如果你想一边阅读本文,一边实践,但是没有 Jenkins 服务可用,又想快速尝试,可以应用 Docker 一个命令快速搭建 Jenkins 服务
docker container run --rm -p 8080:8080 -p 50000:50000 --name=jenkins -v $(pwd):/var/jenkins_home jenkins/jenkins

2021 年了,本地没有 Docker 说不过去了,过来瞧瞧 Docker 系列是否入得了你的法眼?
打开浏览器输入:localhost:8080
- 找到终端的临时密码登陆
- 安装推荐的依赖
- 创建新的 Pipeline 类型的 Item
- 点击左侧 Config,然后在页面底部 Pipeline 部分输入我们接下来写的脚本进行测试就好了

就是这么简单.....
认识 Jenkins 环境变量
Jenkins 环境变量就是通过
env关键字暴露出来的全局变量,可以在 Jenkins 文件的任何位置使用
其实和你使用的编程语言中的全局变量没有实质差别
查看 Jenkins 系统内置环境变量
Jenkins 在系统内置了很多环境变量方便我们快速使用,查看起来有两种方式:
方式一:
直接在浏览器中访问 ${YOUR_JENKINS_HOST}/env-vars.html 页面就可以,比如 http://localhost:8080/env-vars.html ,每个变量的用途写的都很清楚

方式二
通过执行 printenv shell 命令来获取:
pipeline {
agent any
stages {
stage("Env Variables") {
steps {
sh "printenv"
}
}
}
}
直接 Save - Build, 在终端 log 中你会看到相应的环境变量,并且可以快速看到他们当前的值

通常这两种方式可以结合使用
读取环境变量
上面我们说了 env 是环境变量的关键字,但是读取 Jenkins 内置的这些环境变量,env 关键字是可有可无, 但不能没了底裤,都要使用 ${xxx} 包围起来。以 BUILD_NUMBER 这个内置环境变量举例来说明就是这样滴:

如果你在 Jenkins 文件中使用 shell 命令,使用这些内置环境变量甚至可以不用 {}, 来看一下:
pipeline {
agent any
stages {
stage("Read Env Variables") {
steps {
echo "带 env 的读取方式:${env.BUILD_NUMBER}"
echo "不带 env 的读取方式:${BUILD_NUMBER}"
sh 'echo "shell 中读取方式 $BUILD_NUMBER"'
}
}
}
}
可以看到结果是一样一样滴,不管有几种,记住第一种最稳妥

内置的环境变量虽好,但也不能完全满足我们自定义的 pipeline 的执行逻辑,所以我们也得知道如何定义以及使用自定义环境变量
自定义 Jenkins 环境变量
Jenkins pipeline 分声明式(Declarative)和 脚本式(imperative)写法,相应的环境变量定义方式也略有不同,归纳起来有三种方式:

还是看个实际例子吧:
pipeline {
agent any
environment {
FOO = "bar"
}
stages {
stage("Custom Env Variables") {
environment {
NAME = "RGYB"
}
steps {
echo "FOO = ${env.FOO}"
echo "NAME = ${env.NAME}"
script {
env.SCRIPT_VARIABLE = "Thumb Up"
}
echo "SCRIPT_VARIABLE = ${env.SCRIPT_VARIABLE}"
withEnv(["WITH_ENV_VAR=Come On"]) {
echo "WITH_ENV_VAR = ${env.WITH_ENV_VAR}"
}
}
}
}
}
来看运行结果:

注意:
withEnv(["WITH_ENV_VAR=Come On"]) {}这里的 = 号两侧不能有空格,必须是key=value的形式
一个完整的 pipeline 通常会有很多个 stage,环境变量在不同的 stage 有不同的值是很常见的,知道如何设置以及读取环境变量后,我们还得知道如何重写环境变量
重写 Jenkins 环境变量
Jenkins 让人相对困惑最多的地方就是重写环境变量,但是只要记住下面这三条规则,就可以搞定一切了
withEnv(["WITH_ENV_VAR=Come On"]) {}内置函数的这种写法,可以重写任意环境变量- 定义在
environment {}的环境变量不能被脚本式定义的环境变量(env.key="value")重写 - 脚本式环境变量只能重写脚本式环境变量
这三点是硬规则,没涵盖在这 3 点规则之内的也就是被允许的了

三条规则就有点让人头大了,农夫选豆种,举例为证吧
pipeline {
agent any
environment {
FOO = "你当像鸟飞往你的山"
NAME = "Tan"
}
stages {
stage("Env Variables") {
environment {
// 会重写第 6 行 变量
NAME = "RGYB"
// 会重写系统内置的环境变量 BUILD_NUMBER
BUILD_NUMBER = "10"
}
steps {
// 应该打印出 "FOO = 你当像鸟飞往你的山"
echo "FOO = ${env.FOO}"
// 应该打印出 "NAME = RGYB"
echo "NAME = ${env.NAME}"
// 应该打印出 "BUILD_NUMBER = 10"
echo "BUILD_NUMBER = ${env.BUILD_NUMBER}"
script {
// 脚本式创建一个环境变量
env.SCRIPT_VARIABLE = "1"
}
}
}
stage("Override Variables") {
steps {
script {
// 这里的 FOO 不会被重写,违背 Rule No.2
env.FOO = "Tara"
// SCRIPT_VARIABLE 变量会被重写,符合 Rule No.3
env.SCRIPT_VARIABLE = "2"
}
// FOO 在第 37 行重写失败,还会打印出 "FOO = 你当像鸟飞往你的山"
echo "FOO = ${env.FOO}"
// 会打印出 "SCRIPT_VARIABLE = 2"
echo "SCRIPT_VARIABLE = ${env.SCRIPT_VARIABLE}"
// FOO 会被重写,符合 Rule No.1
withEnv(["FOO=Educated"]) {
// 应该打印 "FOO = Educated"
echo "FOO = ${env.FOO}"
}
// 道理同上
withEnv(["BUILD_NUMBER=15"]) {
// 应该打印出 "BUILD_NUMBER = 15"
echo "BUILD_NUMBER = ${env.BUILD_NUMBER}"
}
}
}
}
}
来验证一下结果吧


看到这,基本的设置应该就没有什么问题了,相信你也发现了,Jenkins 设置环境变量和编程语言的那种设置环境变量还是略有不同的,后者可以将变量赋值为对象,但 Jenkins 就不行,因为在 Jenkins 文件中,所有设置的值都会被当成 String, 难道没办法应用 Boolean 值吗?
Jenkins 中使用 Boolean 值
如果设置一个变量为 false ,Jenkins 就会将其转换为 "false", 如果想使用 Boolean 来做条件判断,必须要调用 toBoolean() 方法做转换
pipeline {
agent any
environment {
IS_BOOLEAN = false
}
stages {
stage("Env Variables") {
steps {
script {
// Hello 会被打印出来,因为非空字符串都会被认为是 Boolean.True
if (env.IS_BOOLEAN) {
echo "Hello"
}
// 真正的 Boolean 比较
if (env.IS_BOOLEAN.toBoolean() == false) {
echo "日拱一兵"
}
// 真正的 Boolean
if (!env.IS_BOOLEAN.toBoolean()) {
echo "RGYB"
}
}
}
}
}
}
来看运行结果:

如果你写过 Pipeline,你一定会知道,写 Pipeline 是离不开写 shell 的,有些时候,需要将 shell 的执行结果赋值给环境变量,Jenkins 也有方法支持
Shell 结果赋值给环境变量
实现这种方式很简单,只需要记住一个格式:sh(script: 'cmd', returnStdout:true)
pipeline {
agent any
environment {
// 使用 trim() 去掉结果中的空格
LS_RESULT = "${sh(script:'ls -lah', returnStdout: true).trim()}"
}
stages {
stage("Env Variables") {
steps {
echo "LS_RESULT = ${env.LS_RESULT}"
}
}
}
}

总结
关于 Jenkins 环境变量,了解这些基本上就满足绝大多数应用场景了,当再遇到环境变量问题时,可以回过来翻看一下了,有解决的困惑吗?
个人博客:https://dayarch.top
加我微信好友, 进群娱乐学习交流,备注「进群」
欢迎持续关注公众号:「日拱一兵」
- 前沿 Java 技术干货分享
- 高效工具汇总 | 回复「工具」
- 面试问题分析与解答
- 技术资料领取 | 回复「资料」
以读侦探小说思维轻松趣味学习 Java 技术栈相关知识,本着将复杂问题简单化,抽象问题具体化和图形化原则逐步分解技术问题,技术持续更新,请持续关注......

10分钟搞定让你困惑的 Jenkins 环境变量的更多相关文章
- 【转】让你10分钟搞定Mac--最简单快速的虚拟安装
文章出处:让你10分钟搞定Mac--最简单快速的虚拟安装http://bbs.itheima.com/thread-106643-1-1.html (出处: 黑马程序员训练营论坛) 首先说明一下. 第 ...
- OpenCV3.4.1快速集成到Android studio中,10分钟搞定
OpenCV3.4.1快速集成到Android studio中,10分钟搞定 转载 https://blog.csdn.net/yu540135101/article/details/8259 ...
- Python基于VS2013 开发环境搭建 Hello World 10分钟搞定
1.先下载Python 安装 Next ->安装完成 2.以前安装过VS2013 打开VS2013 文件->新建项目 (此时如果没有Python Application,请点击里面的安装插 ...
- 10分钟搞定 Java 并发队列好吗?好的
| 好看请赞,养成习惯 你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it ...
- 【前端知识体系-JS相关】10分钟搞定JavaScript正则表达式高频考点
1.正则表达式基础 1.1 创建正则表达式 1.1.1 使用一个正则表达式字面量 const regex = /^[a-zA-Z]+[0-9]*\W?_$/gi; 1.1.2 调用RegExp对象的构 ...
- 10分钟搞定nginx实现负载均衡
10.1 负载均衡的概念 对用户请求的数据进行调度的作用 对用户访问的请求网站可以进行压力的分担 10.2 常见的代理方式 10.2.1 正向代理 10.2.2 反向代理 10.3 负载均衡的部署环节 ...
- 10分钟搞定react-router
1.路由的安装: $ npm install -S react-router 2.引入路由文件 import {Router, Route, browserHistory} from 'react-r ...
- 10分钟搞定webpack打包
入门前端这个职位近三年的时间了,但是脑子里的东西不多也不少,今天就从脑袋里把新版本的webpack打包过程拔出来给大家鲁一遍,就算帮助那些小白了,废话不多说,开始鲁起来,大家跟着我一起撸... 首先, ...
- 一分钟搞定Java高频面试题
一分钟搞定Java高频面试题 一.变量赋值和计算 题目: public static void main(String[] args) { int i = 1; i = i++; int j = i+ ...
随机推荐
- PyQt(Python+Qt)学习随笔:窗口的布局设置及访问
老猿Python博文目录 老猿Python博客地址 在Qt Designer中,可以在一个窗体上拖拽左边的布局部件,在窗口中进行布局管理,但除了基于窗体之上进行布局之外,还需要窗体本身也进行布局管理才 ...
- Leetcode学习笔记(5)
之前断了一段时间没做Leetcode,深感愧疚,重新续上 题目1 ID104 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点 ...
- flask中SQLAlchemy学习
------------------------------------2019-08-22 17:53:54更新------------------------------ SQLALchemy实在 ...
- 一篇文章掌握Nginx核心文件结构
1 Nginx核心配置结构 2 配置模块详解 设置worker进程的用户,指的linux中的用户,会涉及到nginx操作目录或文件的一些权限,默认为nobody user root; worker进程 ...
- Elements-of-Python_04_Function
(内容包括函数.递归.Lambda.作用域等) 1. 函数 1.1 函数概述 函数是对程序逻辑进行结构化和过程化的一种编程方法,用于封装一个特定的功能,表示一个功能或者行为.函数是可以重复执行的语句块 ...
- HashMap 中 Key 类型的选择
什么对象可以作为HashMap的key值? 从HashMap的语法上来讲,一切对象都可以作为Key值.如:Integer.Long.String.Object等.但是在实际工作中,最常用的使用Stri ...
- Linux内核中container_of宏的详细解释
上一节拒绝造轮子!如何移植并使用Linux内核的通用链表(附完整代码实现)我们在分析Linux内核链表的时候注意到内核在求解结构体偏移的时候巧妙的使用了container_of宏定义,今天我们来详细剖 ...
- 题解洛谷P1538【迎春舞会之数字舞蹈】
方法:暴力,判断,输出 本题为了更好理解建议各位可以复制样例来研究,甚至可以复制题解来测试思想,相信大家不会抄. 有什么不好的请大佬们在评论里指出,谢谢 #include <bits/stdc+ ...
- BloomFilter中保存的数据量
结果 /** * @author WeiJiQian * BF_CARDINAL_THRESHOLD BF_FALSE_POSITIVE_RATE 保存的数据量 * 100,0000 0.01 391 ...
- Core3.0返回的Json数据大小写格式问题
前言 测试发现,CoreWebAPI返回的Json数据,会将字段的首字母转换为小写, 经百度得,返回数据会默认驼峰命名,导致的. 随即百度, https://www.cnblogs.com/cdone ...