考虑以下gitlab-ci.yml:
...
variables:
var_A: 'Hello'
before_script:
- export var_B="World"
step1:
stage: build
script:
- chmod u+x run.sh && source run.sh
鉴于run.sh包含以下脚本:
echo $var_A
echo $var_B
我注意到CI运行管道之后,var_A
解析为“ Hello”,但是调用echo $var_B
并不会在屏幕上显示任何内容。这到底是怎么回事?有什么方法可以在shell脚本中访问var_b?
答案 0 :(得分:0)
如果某个进程启动了一个子进程,并且该子进程设置了环境变量,则这些变量仅在子进程中以及在该子进程的子进程中可见,它们永远不会传播到父进程,而父进程也不容易一种访问其子进程环境的方法。
对于GitLab CI运行程序,运行程序将启动一个子进程来运行您的脚本指令,即外壳程序(默认为/bin/sh
)。当您在该Shell中更改环境时,此更改仅对Shell及其所有子进程可见(例如,您正在执行的命令)。
然而,运行您的before_script
指令的外壳不必与以后运行您的script
指令的外壳相同,通常这是两个单独的外壳。尤其是您的before_script
是全局的,因此它对所有作业都运行一次,而所有作业可以并行运行,因此都需要自己的外壳程序。在一个外壳中所做的环境更改以后在其他外壳中运行的代码将看不到。
作为解决方法,您可以使用文件:
variables:
var_A: 'Hello'
before_script:
- echo 'export var_B="World"' > somefile.env
step1:
stage: build
script:
- source somefile.env
- chmod u+x run.sh && source run.sh
顺便说一句,如果您source
脚本文件不需要执行,则不需要chmod
。如果您想以./run.sh
的身份运行脚本,则将需要它。区别在于source
在您当前的shell中执行脚本代码,而./run.sh
将创建一个子shell并在其中执行代码。在子外壳中运行时,run.sh
将看到您的所有环境,但对它的更改将对run.sh
及其调用的任何进程都是私有的,而如果您执行以下操作,这些更改将传播到您的主外壳中source run.sh
。