インラインで宣言された環境変数を区別する賢い方法はありますか?

インラインで宣言された環境変数を区別する賢い方法はありますか?

子プロセスとしてエクスポートされたインライン宣言/定義環境変数と、すでに存在するか継承されている環境変数を区別したいと思います。

$ 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"
...

これは、シェルオペレーティング環境(例えば、umなど)を無視すると大きな混乱を招く可能性があります。 ENVSなどの追加マニフェストを使用して使用したい環境をホワイトリストに追加できますが、これはさまざまな理由で問題になりますSHELLPATH

 $ 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"

第一に、本当に混乱しており、第二に、ラッパーの予想動作が基本ターゲットの予想動作と一致しなければならないという原則に違反します。以下のようにgoコマンドにenvを渡しましたが、うまくいきません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

明らかなハードコーディングに加えて、この問題を解決する他の方法があるかどうかはわかりませんが、過度に賢くて簡潔なものがあれば見たいです。

関連情報