在使用jenkins过程中,发现执行shell读取不到/etc/profile以及用户下.bash_profile设置的环境变量。
具体原因 参考 从jenkins远程执行shell源码分析。
在默认的情况下,Jenkins执行shell会在节点上tmp目录生成类似hudson224519953209659762.sh(后面数字根据规则生成),具体执行的命令如:
/bin/sh -xe /tmp/hudson224519953209659762.sh。如果Execute Shell里面具体命令为以下内容:
#!/bin/bash +x......
那么根据上面代码,具体执行的命令就会变成/bin/bash +x /tmp/hudson224519953209659762.sh
知道jenkins执行shell的原理后,下面了解一下Linux交互式和非交互式shell、登录和非登录shell之间的区别。
1.交互式shell(interactive shell)和非交互式shell(non-interactive shell)
交互式的shell会有一个输入提示符,并且它的标准输入、输出和错误输出都会显示在控制台上。这种模式也是大多数用户非常熟悉的:登录、执行一些命令、退出。当你退出后,shell也终止了。
非交互式shell是bash script.sh这类的shell。在这种模式下,shell不与你进行交互,而是读取存放在文件中的命令,并且执行它们。当它读到文件的结尾EOF,shell也就终止了。
2.登录式shell(login shell)和非登陆式shell(no-login shell)
需要输入用户名和密码的shell就是登陆式shell。因此通常不管以何种方式登陆机器后用户获得的第一个shell就是login shell。不输入密码的ssh是公钥打通的,某种意义上说也是输入密码的。
非登陆式的就是在登陆后启动bash等,即不是远程登陆到主机这种。
对于常用环境变量设置文件,整理出如下加载情况表:
文件 | 非交互+登陆式 | 交互+登陆式 | 交互+非登陆式 | 非交互+非登陆式 |
---|---|---|---|---|
/etc/profile | 加载 | 加载 | ||
/etc/bashrc | 加载 | 加载 | ||
~/.bash_profile | 加载 | 加载 | ||
~/.bashrc | 加载 | 加载 | 加载 | |
BASH_ENV | 加载 |
执行脚本,如bash script.sh是属于non-login + non-interactive
所以jenkins默认情况下/bin/sh -xe /tmp/hudson224519953209659762.sh 是属于non-login + non-interactive
可以通过-i参数和-l参数让bash为login shell and interactive shell,就可以读取/etc/profile和~/.bash_profile等文件。
即在jenkins Execute Shell里可以这么写
#!/bin/bash -ilex...#脚本内容...
对于e参数表示一旦出错,就退出当前的shell,x参数表示可以显示所执行的每一条命令。