返回「计算机、信息技术与工程」

【Jenkins】用户与环境变量问题

更多
Markdown 结构化数据
本文目录 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/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程序,传入参数来执行。

assets/0028 - 【Jenkins】用户与环境变量问题__resource-001-2af138a09e6a.png

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));

打印结果:

assets/0028 - 【Jenkins】用户与环境变量问题__resource-006-e9df4973a88e.png

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

assets/0028 - 【Jenkins】用户与环境变量问题__resource-002-a29fc8a59bf2.png

这个环境变量在构建(Build)执行时候才生效。

使用Initialization files

如果 Launch agents via SSH,可以在节点的配置中添加命令来加载profile文件: Configure -> Launch method -> Launch Launch agents via SSH -> Prefix Start Agent Command

注意:每条语句都要使用分号结尾

assets/0028 - 【Jenkins】用户与环境变量问题__resource-003-63fd855a5ab5.png

Jenkins会在启动代理进程时,将上述命令加入到shell语句当中

string a = "test";
string tmp = "est";
string b = "t" + tmp;
Console.WriteLine(string .ReferenceEquals(str1, str2));

环境变量会加到这个Node的Environment Variable列表中:

assets/0028 - 【Jenkins】用户与环境变量问题__resource-004-5d201cbc834b.png

某个Project的环境变量

Pipeline脚本中使用

可以在各个级别上设置环境变量

assets/0028 - 【Jenkins】用户与环境变量问题__resource-005-ceb5c8dfbadf.png

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.");