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+ ...
 
随机推荐
- 如何使用 K8s 两大利器"审计"和"事件"帮你摆脱运维困境?
			
概述 下面几个问题,相信广大 K8s 用户在日常集群运维中都曾经遇到过: 集群中的某个应用被删除了,谁干的? Apiserver 的负载突然变高,大量访问失败,集群中到底发生了什么? 集群节点 Not ...
 - 分布式存储系统-HDFS
			
1 HDFS 架构 HDFS作为分布式文件管理系统,Hadoop的基础.HDFS整体架构包括:NameNode.DataNode.Secondary NameNode,如图: HDFS采用主从式的分布 ...
 - [Windows] 在 Microsoft Docs 网站中挖掘 MVVM 的各种学习资源
			
最近写了一些 MVVM 框架的文章,翻了一些 Microsoft Docs 的文档,顺便就对 MVVM 本身来了兴致,想看看更多当年相关的文档.在 MVVM 出现后十多年,我在不同的场合见到过多种 M ...
 - golang omitempty 总结
			
golang omitempty 总结 在使用Golang的时候,不免会使用Json和结构体的相互转换,这时候常用的就是 json.Marshal和json.Unmarshal两个函数. 这时候在定义 ...
 - 助力用户选择更优模型和架构,推动 AI机器视觉落地智能制造
			
智能制造的全新 "视界" 由互联网大潮掀起的技术进步,推动着智能制造成为传统制造行业面向未来.寻求突破的关键路径.通过融合机器人.大数据.云计算.物联网以及 AI 等多种技术, ...
 - JQuery统一复写美化项目中所有radio单选按钮样式
			
老项目要升级改版,对于分散在各页面的样式不好处理,怕有遗漏,尤其是优化input表单,修改其默认样式,接下来,我将给大家分享一下,我在项目中的总结. 效果 上代码: 1.简单搞一搞 CSS,此处代码有 ...
 - 短视频去水印v1.0(还支持74个平台)
			
软件介绍: 一款很好用的短视频去水印软件,支持74个平台无水印解析,还支持批量视频解析只需要输入账号主页链接就可以了哦,快来下载试试吧! 软件版本:1.0 支持系统:安卓 软件大小:22. ...
 - 性能测试工具 jmeter 分布式压力测试实操
			
性能测试工具 jmeter 分布式压力测试实操 本文在Non-GUI Mode下进行,准备好三台有jdk环境,linux操作系统,同一局域网测试机器,运行两台slave,一台master机器,进行分布 ...
 - 【译】理解Rust中的Futures (一)
			
原文标题:Understanding Futures In Rust -- Part 1 原文链接:https://www.viget.com/articles/understanding-futur ...
 - 环境篇:Atlas2.1.0兼容CDH6.3.2部署
			
环境篇:Atlas2.1.0兼容CDH6.3.2部署 Atlas 是什么? Atlas是一组可扩展和可扩展的核心基础治理服务,使企业能够有效地满足Hadoop中的合规性要求,并允许与整个企业数据生态系 ...