安全保存和恢复环境变量

sha*_*ker 4 shell environment-variables

我有一个脚本,可以解析基本.env文件并将其内容导出为环境变量,然后再采取进一步操作:

set -eu

test -f .env && load_dotenv

exec ./foobar x y z "$@"
Run Code Online (Sandbox Code Playgroud)

但是,这会导致定义的环境变量.env优先于用户 shell 中定义的环境变量。我想要相反的行为:我希望在 shell 中显式设置的环境变量优先于文件中定义的任何内容.env。

因此,我希望在运行之前“保存”当前环境load_dotenv,然后在运行后“重新应用”保存的环境load_dotenv:

set -eu

user_env="$( env )"

test -f .env && load_dotenv

reapply_env "$user_env"  # ???

exec ./foobar x y z "$@"
Run Code Online (Sandbox Code Playgroud)

我如何实现reapply_env,以便它可以处理任意环境变量?据我所知,除此之外的任何字节\0在环境变量中都是有效的,所以我想确保这适用于任何任意环境变量。例如,在环境变量中嵌入换行符有合法的(尽管不常见)用例。

我愿意接受特定于 shell 的答案,但假设我使用的是 Bourne 风格的 shell(Bash、Ksh、Zsh 等)。

忽略安全问题。假设我在受信任、受控的环境中操作,并且任何像“欺骗开发人员下载恶意文件.env”这样的场景都涉及更广泛的安全问题,超出了本问题的范围。

编辑:如何避免覆盖环境变量是一个很好的问题,但这不是我有兴趣回答这个特定问题的内容。如果还没有重复的内容,我可以为此单独发布一篇。

Whi*_*Owl 6

Bash 能够在设置环境变量之前对其进行测试。所以你可以.env这样写你的文件:

VAR1="default value"
VAR2=${VAR2:="default value"}
Run Code Online (Sandbox Code Playgroud)

现在,如果您有一个新会话(批处理或终端)并执行以下操作:

$ source .env
$ echo $VAR1 - $VAR2
default value - default value
$ VAR1="my value"
$ VAR2="my value"
$ source .env
$ echo $VAR1 - $VAR2
default value - my value
Run Code Online (Sandbox Code Playgroud)

该语法如下所述:https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion

和ksh都zsh具有相似的能力,对于“如果变量不存在则为该变量赋值”任务具有相同的语法:

https://www.ibm.com/docs/en/aix/7.1?topic=shell-parameter-substitution-in-korn-posix

https://zsh.sourceforge.io/Doc/Release/Expansion.html#Parameter-Expansion