【Jenkins】用户与环境变量问题
本文目录 23 个章节
【Jenkins】用户与环境变量问题
# 【Jenkins】用户与环境变量问题
创建时间:2021/7/6 16:08
- 综述
- Jenkins运行Shell的机制
- SSH远程登录与环境变量
- 运行shell脚本
- 修改What shell is used
- Jenkins不同层次环境变量的加载特性和时机
- 全局配置、节点配置和节点本身环境变量之间的关系
- 节点本身环境变量加载方式
- Master Windows
- Master Linux
- Slave Windows
- Slave MacOS
- Pipeline中通过environment字段
- Jenkins环境变量设置方式
- 全局变量
- 节点本身的环境变量
- 在Jenkins中设置全局变量
- 使用Initialization files
- 某个Project的环境变量
- Pipeline脚本中使用
- shell脚本中设置
- 某个Shell进程(会话)的环境变量
- 内置环境变量
- Jenkins运行Shell的机制
综述
Jenkins下自动运行shell/bat与手动运行、在命令行/终端下运行的区别主要在于两点:
- 登陆的用户身份不同,导致权限不同
- 加载的环境变量不同,导致一些命令无法找到,或者运行结果出错
Jenkins运行Shell的机制
SSH远程登录与环境变量
Jenkins使用SSH远程登录Unix系统时,实质上是直接在SSH登录的命令中加入了指令,属于non-interactive + non-login shell,类似于以下语句:
string a = "test";
string tmp = "est";
string b = "t" + tmp;
Console.WriteLine(string .ReferenceEquals(str1, str2));
因此, 不会读取任何文件 (profile等) 因此,Jenkins远程执行任务,使用的环境变量只能使用Jenkins来配置,用户在profile等文件中配置的变量是无效的。有两种思路:
- 直接设置环境变量。
- 使用source指令,使profile或rc文件生效。
运行shell脚本
Jenkins运行Shell命令的机制与以下代码类似,每执行一段sh命令,shell都会启动一个sh程序,传入参数来执行。

string a = "test";
string tmp = "est";
string b = "t" + tmp;
Console.WriteLine(string .ReferenceEquals(str1, str2));
修改What shell is used
方法一:Manage Jenkins --> Configure System --> Shell executable
(不推荐)因为这会修改在所有节点上运行shell的路径,如果windows和linux系统混用,会导致出错。
方法二:declare your shell on the first line of your script as you do in any shell script file:
string a = "test";
string tmp = "est";
string b = "t" + tmp;
Console.WriteLine(string .ReferenceEquals(str1, str2));
Jenkins不同层次环境变量的加载特性和时机
全局配置、节点配置和节点本身环境变量之间的关系
- 全局配置:Config System当中设置Global properties -> Environment variables
- 节点配置:可以在某个节点设置Configure -> Environment variables
- 节点本身:Jenkins启动某个节点时,会加载这个节点上的环境变量。
全局配置和节点配置都可以引用节点本身的环境变量。节点本身的环境变量在初始化时就会加载好,而配置当中环境变量的设定在此之后。 全局配置和节点配置的环境变量,如果名称不同,并且在不出现循环引用的情况下,可以互相引用。 如果名称相同,优先使用节点的配置,全局的配置不生效。节点配置中的环境变量所引用的环境变量来自全局配置,还是来及节点本身,笔者暂时没有确定,两种情况似乎都会出现。
总之,Jenkins中对全局、节点配置的环境变量都可以引用节点本身的环境变量,全局和节点的配置也可以相互引用,但是初始化顺序不明确,如果出现循环引用,会产生多次递归现象。
节点本身环境变量加载方式
Master Windows
Jenkins以服务的形式安装运行,系统变量会加载,用户变量不会被加载。修改了环境变量后,需要重启Jenkins才能加载到。
Master Linux
以用户jenkins的身份登录,大多数环境变量都是与Jenkins自身有关的,基本不会加载什么用户配置文件里的环境变量。
Slave Windows
在Windows节点上环境变量会加载的比较全。系统变量和用户变量都会被加载到。 双击运行或者cmd运行,就是以当前登录的用户身份运行的,系统变量和用户变量都会被加载到。 如果命令行运行,那么在命令行设置过的环境变量会被继承。
Slave MacOS
不会读取任何环境变量配置文件 。可以在Prefix Start Agent Command中进行设置。
Pipeline中通过environment字段
通过Enviroment字段的方式设置的环境变量,不能引用已有的环境变量。 设置代码如下:
string a = "test";
string tmp = "est";
string b = "t" + tmp;
Console.WriteLine(string .ReferenceEquals(str1, str2));
打印结果:

Jenkins环境变量设置方式
- 全局环境变量(所有节点,所有Job都生效的)
- 某个节点(node)的环境变量
- 某个项目(project)的环境变量
- 某次构建(build)的环境变量
全局变量
Manage Jenkins -> Global properties -> Environment variables -> Add
节点本身的环境变量
node上执行的的所有 shell 命令都会继承这个node的环境变量。
在Jenkins中设置全局变量
Manage node -> Configure -> Environment variables -> List of variables -> Add

这个环境变量在构建(Build)执行时候才生效。
使用Initialization files
如果 Launch agents via SSH,可以在节点的配置中添加命令来加载profile文件: Configure -> Launch method -> Launch Launch agents via SSH -> Prefix Start Agent Command
注意:每条语句都要使用分号结尾

Jenkins会在启动代理进程时,将上述命令加入到shell语句当中
string a = "test";
string tmp = "est";
string b = "t" + tmp;
Console.WriteLine(string .ReferenceEquals(str1, str2));
环境变量会加到这个Node的Environment Variable列表中:

某个Project的环境变量
Pipeline脚本中使用
可以在各个级别上设置环境变量

shell脚本中设置
可以通过-i参数和-l参数让bash为login shell and interactive shell,就可以读取/etc/profile和~/.bash_profile等文件。
即在jenkins Execute Shell里可以这么写
string str1 = String.Empty;
string str2 = String.Empty;
str2 = String.Intern(sb.ToString());
if((object)str1==(object)str2)
Console.WriteLine("The strings are equal.");
else
Console.WriteLine("The strings are not equal.");
某个Shell进程(会话)的环境变量
- 可以使用export命令设置
- 可以使用Initialization files - 在shell命令前添加描述
string str1 = String.Empty;
string str2 = String.Empty;
str2 = String.Intern(sb.ToString());
if((object)str1==(object)str2)
Console.WriteLine("The strings are equal.");
else
Console.WriteLine("The strings are not equal.");
内置环境变量
string str1 = String.Empty;
string str2 = String.Empty;
str2 = String.Intern(sb.ToString());
if((object)str1==(object)str2)
Console.WriteLine("The strings are equal.");
else
Console.WriteLine("The strings are not equal.");
string str1 = String.Empty;
string str2 = String.Empty;
str2 = String.Intern(sb.ToString());
if((object)str1==(object)str2)
Console.WriteLine("The strings are equal.");
else
Console.WriteLine("The strings are not equal.");