有什么巧妙的方法来区分内联声明的环境变量吗?

有什么巧妙的方法来区分内联声明的环境变量吗?

我想区分导出到子进程的内联声明/定义的环境变量和已经存在/继承的环境变量。

$ export NODEJS=8
$ FU=BAR sh -c 'echo $FU $NODEJS'

具体用例是 cmd 包装器/装饰器,我们在其中封装容器使用情况(这只是一个示例)。

/tmp $ cat ./go.sh 
#!/bin/sh
set -eu

docker run \
    --rm \
    --volume $PWD:/opt/main \
    --workdir /opt/main \
golang:1.15 go "${@--h}"
/tmp $ go version
go version go1.15.5 darwin/amd64
/tmp $ mkdir -p /tmp/bin
/tmp $ ln -sf /tmp/go.sh /tmp/bin/go
/tmp $ chmod +x /tmp/go.sh 
/tmp $ PATH=/tmp/bin:$PATH
/tmp $ go version
Unable to find image 'golang:1.15' locally
1.15: Pulling from library/golang
756975cb9c7e: Pull complete 
d77915b4e630: Pull complete 
5f37a0a41b6b: Pull complete 
96b2c1e36db5: Pull complete 
145393847161: Pull complete 
3f8843661db9: Pull complete 
218d240e42d4: Pull complete 
Digest: sha256:0edb8df3d92a2ccf84d3245c8b0cc31edd6d23f9c3da3e07c8e2bd96eea34547
Status: Downloaded newer image for golang:1.15
go version go1.15.6 linux/amd64

我强调封装,因为对于上述包装器脚本的最终用户来说,无论我们从 Darwin 主机还是容器调用,在接口和/或期望方面都不应该有任何差异。这意味着,没有像下面这样的空白环境:

/tmp $ env -i FU=BAR sh -c 'echo $FU $NODEJS'
BAR

要将环境变量传递给 docker 运行时,我可以这样做:

$ cat <<eof | head -n3
> docker run \
> --rm \
> --volume $PWD:/opt/main \
> --workdir /opt/main \
> $( env -0 | xargs -0 -L1 printf '--env "%s"\n' ) \
> golang:1.15 go "${@--h}"
> eof
docker run --rm --volume /tmp:/opt/main --workdir /opt/main --env "TERM_PROGRAM=Apple_Terminal"
--env "SHELL=/bin/bash"
--env "TERM=xterm-256color"
...

当覆盖 shell 操作环境(如,嗯,,等)时,这会严重破坏。SHELL我们PATH可以使用额外的清单 y 环境(如 ENVS)将要使用的环境列入白名单,但由于几个原因,这是有问题的。

 $ cat /tmp/go.sh 
#!/bin/sh
set -eu

cat <<eof
docker run \
    --rm \
    --volume $PWD:/opt/main \
    --workdir /opt/main \
    $( echo $ENVS | xargs -n1 -- sh -c 'printf -- "--env %s=%s\n" $1 ${!1}' _) \
golang:1.15 go "${@--h}"
eof
$ ENVS="FU NODEJS" FU=BAR /tmp/go.sh 
docker run  --rm    --volume /tmp:/opt/main     --workdir /opt/main     --env FU=BAR
--env NODEJS=8 golang:1.15 go "-h"

首先,它确实很混乱,其次,它违反了包装器的预期行为应与底层目标的预期行为相匹配的原则。如果我将 envs 传递给我的 go 命令,如下所示,并且它们不起作用,并且我花了一天时间才意识到它们需要在 中指定ENVS,我会不太兴奋。

# fails to build appropriately targeted binary, but doesn't fail to build
$ GOOS=linux GOARCH=ppc64 go build
# this makes me mad
$ ENVS="GOOS GOARCH" GOOS=linux GOARCH=ppc64 go build

我不知道除了明显的硬编码之外是否有任何不同的方法来解决这个问题,但如果有人有任何过于聪明和简洁的东西,我很乐意看到它。

相关内容