Makefile 内のコマンドに環境変数を渡す
Makefile は 長い コマンド等の手軽なコマンド化を行うのに便利です。
一方で、 Makefile 内では、複数行でコマンドを渡すと、1つ1つが別々なプロセスで扱われるなど、 bash に コマンドを1つ1つ実行するのとは違う挙動を示します。
本記事では、 Makefile 内で実行するコマンドに実行時に環境変数を渡す方法を記載します。
Makefile の サンプルは以下のリポジトリに保存しています。
環境変数を .env ファイルから渡すユースケース
Google Cloud Storage や Azure の Blob Storage 等のサービスアカウントやアクセスキーの秘密にすべき情報のベストプラクティスの1つは、環境変数経由で渡すようにし、gitにはコミットしないようにするということがあります。
Make での実行時には、実行環境の環境変数は引き継がれますが、 Makefile の実行時に環境変数を渡したいということがあります。
例えば Makefile
以下のように記載して実行すると、 ${MY_SECRET_KEY}
の値は空になり、 MY_SECRET_KEY
は渡せていません。
run-non-secure:
export MY_SECRET_KEY="hoge" && echo ${MY_SECRET_KEY}
実行例
$ make run-non-secure
# 何も出力されない
なぜか。
Makefile 内の変数の種別
Makefile内で利用する変数には以下の3つがあります。
- 環境変数: シェルで定義される変数。定義を実行したプロセスと、そのプロセスを親とする子プロセスまで引き継がれる。
- シェル変数: シェルで定義される変数。定義を実行したプロセスでしか有効ではありません。
- make変数: Makefile の中で定義される変数。 Makefile の中でのみ有効です。
参考:
ちょっとMakefileくん! .envに書いた環境変数読んで!!!!!なんで読んでくれないの!?
makefile 内では、$一つの ${ENV_KEY_NAME}
は make 変数として扱われます。
一方で、 export しているのは、 シェルで定義するので、 環境変数として定義されてしまうため、
定義している場所と参照している場所がことなるため、内容が読めていませんでした。
環境変数やシェル変数にアクセスするためには、 Makefile 内では、
変数名に $$
2つをつけて以下のようにすると読むことができます。
run-non-secure-env-var:
export MY_SECRET_KEY="hoge" && echo $${MY_SECRET_KEY}
実行例
$ make run-non-secure-env-var
hoge
セキュアにするには
先程の例では export の 内容を Makefile に直書きしていました。
しかし、セキュリティ上 git 上に Secret Key を残すことは良くないので、
Secret については、 .env
ファイルを別に用意して、 git にコミットする以外の方法で受け渡すようにすることが望ましいです。
なので以下のようにします。
# 本来はこのファイルは git には含めません
MY_SECRET_KEY="hoge"
set -a && source secrets.env && set +a を行うことで、 secrets.env の内容を 今の環境変数に追加できます。
run-secure-env-var:
set -a && source secrets.env && set +a && echo $${MY_SECRET_KEY}
実行例
$ make run-secure-env-var
hoge
参考記事
Makefileで、実行するコマンドに環境変数を渡す方法
ちょっとMakefileくん! .envに書いた環境変数読んで!!!!!なんで読んでくれないの!?
makeで環境変数とMakefileの変数、引数の値の内どの値が参照されるか