Gitlab CI:访问环境变量

Arv*_*nje 4 shell gitlab gitlab-ci

考虑以下 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 Code Online (Sandbox Code Playgroud)

鉴于 run.sh 包含以下脚本:

echo $var_A
echo $var_B
Run Code Online (Sandbox Code Playgroud)

我注意到 CI 运行管道后,var_A解析为“Hello”,但是调用echo $var_B不会在屏幕上打印任何内容。这里究竟发生了什么?有没有办法在shell脚本中访问var_b?

Mec*_*cki 5

如果一个进程启动了一个子进程并且该子进程设置了环境变量,这些变量仅在子进程和子进程的子进程中可见,它们永远不会传播到父进程,父进程也没有简单的方法来访问其子进程的环境。

对于 GitLab CI 运行器,运行器将启动一个子进程来运行您的脚本指令,即 shell(/bin/sh默认情况下)。当您更改该 shell 中的环境时,此更改仅对该 shell 及其所有子进程可见(例如您正在执行的命令)。

然而,运行指令的 shellbefore_script不必与稍后运行script指令的 shell 相同,通常它们是两个单独的 shell;特别是因为您before_script是全局的,所以它对所有作业运行一次,而所有作业都可以并行运行,因此都需要自己的外壳。您在一个 shell 中对环境所做的更改对于稍后在其他 shell 中运行的代码将不可见。

作为解决方法,您可以使用文件:

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
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您source是脚本文件,则它不需要可执行,因此chmod不需要。如果您想将脚本运行为./run.sh. 区别在于,source在当前 shell 中执行脚本代码,而./run.sh会创建一个子 shell 并在那里执行代码。在子 shell 中运行时,run.sh将看到您的所有环境,但对它的更改将是私有的run.sh及其调用的任何进程,而如果您执行source run.sh.