使用 `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 "$(< "$1")" ...
) 不起作用。它只会设置一个带有嵌入式换行符的环境变量,这将使env
输出看起来正确,但set
和类似的会显示值错误
一种安全且 Shellcheck-clean 的方法是将文件的行读入一个数组,并将每一行作为单独的参数传递给 env
:
readarray -t settings <"$1"
env "$settings[@]" ...
【讨论】:
第一个解决方案对您从文件中读取的字符串做出了很多的假设;第二个做的更少,但仍然有一些。<
在$(< "$1")
中是什么意思?
@VadiemJanssens,见Command Substitution (Bash Reference Manual)。 $(< file)
与$(cat file)
相似,但它更快(因为它不创建子进程)并且它可以处理不寻常的文件名(特别是以-
开头的文件名,包括一个名为-
的文件)。跨度>
env "$(< "$1")" ...
不起作用。它只会设置一个带有嵌入式换行符的环境变量,这将使env
输出看起来正确,但set
和类似的会显示值是错误的
@thatotherguy,感谢您报告我的错误。我被化妆品的正确性愚弄了。我已经更新了答案。以上是关于使用 `env` 命令和通过文件传递环境变量的最佳方式的主要内容,如果未能解决你的问题,请参考以下文章
在 Vue.js 中构建期间传递要由 .env.[mode] 文件使用的参数(命令行)
我需要通过 gitlab-ci 中的 ssh 将 env 变量传递给 docker
Heroku.yml 文件。如何从 .env 文件传递环境变量?