使用 `env` 命令和通过文件传递环境变量的最佳方式

Posted

技术标签:

【中文标题】使用 `env` 命令和通过文件传递环境变量的最佳方式【英文标题】:Best way of using `env` command and passing environment variables by file 【发布时间】:2020-04-08 18:15:36 【问题描述】:

我们目前有一个命令,仅用于为以下参数/命令设置环境。环境变量由一个文件设置,通过一个简单的cat 命令:

env $(cat "$1") <rest of the command>

但是,shellcheck 似乎将此标记为“引用此内容以防止分词。shellcheck(SC2046)”。

处理此错误的最佳方法是什么,因为我不确定是否通过简单地忽略这种特殊情况来确定我是否正确?据我所知,有多种路线可供选择(使用xargs,遵循"useless cat" 的原则等)。

示例环境文件:

VARIABLE_1=TEST
VARIABLE_2=TEST2

更新

我希望社区就如何编写此类.env 文件以及如何读取这些文件达成共识。文件和解释器应该比我们在命令之前内联更多的魔术技巧。

【问题讨论】:

为什么不在文件中的每个变量声明前加上export 并直接获取它(可能在子shell 中以保持当前环境清洁)? 对于您的用例而言,该错误可能有点过于琐碎。引用整个替换应该消除该警告。但是看看你的文件内容会很有趣 GNU env(以空结尾的字符串)和 BSD env(转义处理和拆分)都有处理这个问题的选项,尽管两者都需要对文件进行一些预处理。跨度> 唯一正确要做的就是对文件进行 NUL 分隔,使其内容与在 Linux 上阅读 /proc/self/environ 得到的内容相同。否则,并非所有环境变量都可以在内容中表示(特别是包含文字换行符的环境变量会出错)。 考虑在有人运行export 'my_harmless_var='$'\n''LD_LIBRARY_PATH=/tmp/evil.so' 后尝试创建和使用换行符分隔的文件会发生什么;原本无害的变量变成了恶意变量。这忽略了您只是破坏故意包含换行符的无害变量的情况,因为它们包含要运行的代码或诸如此类的东西。 【参考方案1】:

Shellcheck(像往常一样)抱怨缺少引号是正确的。如果值具有嵌入的空格,则代码将中断,如果它们包含 shell 通配符,则代码可能会中断。

添加引号 (env "$(&lt; "$1")" ...) 不起作用。它只会设置一个带有嵌入式换行符的环境变量,这将使env 输出看起来正确,但set 和类似的会显示值错误

一种安全且 Shellcheck-clean 的方法是将文件的行读入一个数组,并将每一行作为单独的参数传递给 env

readarray -t settings <"$1"
env "$settings[@]" ...

【讨论】:

第一个解决方案对您从文件中读取的字符串做出了很多的假设;第二个做的更少,但仍然有一些。 &lt;$(&lt; "$1") 中是什么意思? @VadiemJanssens,见Command Substitution (Bash Reference Manual)。 $(&lt; file)$(cat file) 相似,但它更快(因为它不创建子进程)并且它可以处理不寻常的文件名(特别是以- 开头的文件名,包括一个名为- 的文件)。跨度> env "$(&lt; "$1")" ... 不起作用。它只会设置一个带有嵌入式换行符的环境变量,这将使env 输出看起来正确,但set 和类似的会显示值是错误的 @thatotherguy,感谢您报告我的错误。我被化妆品的正确性愚弄了。我已经更新了答案。

以上是关于使用 `env` 命令和通过文件传递环境变量的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章

在 Vue.js 中构建期间传递要由 .env.[mode] 文件使用的参数(命令行)

Linux中使用export命令设置环境变量

我需要通过 gitlab-ci 中的 ssh 将 env 变量传递给 docker

Heroku.yml 文件。如何从 .env 文件传递​​环境变量?

使用 Docker 和 PHP 从 env 文件加载环境变量

环境变量的查看—env和printenv(环境变量打印)