🤢
安直に .env ファイルを export しないで欲しい
2022/06/19
必要に迫られたので Docker dotenv 互換の function を作りました(Bash 以外もいけるようにしました)
追記: そもそも .env の syntax は統一仕様がなく、ツールによってまちまちです。以下の例は Docker の食べる .env を元に記述しており、Ruby/JS実装の dotenv では異常なく動作する例も存在します。
タイトルの通りです。以下のようなコードはやめましょう。
export $(cat .env)
.env ファイルの記法は Bash などのシェルが定義している変数宣言シンタックスとは異なり、互換性はありません。試しに以下は各行が全て valid な .env 記法ですが、実行するまでもなく動作しないことが分かります。
including_space=hello world
push_to_background=hello &
pipe_to=hello | world
redirect_to=hello > world
end_statement=hello; world
comment_tailing=hello # world
またこれらの反例を実行したときのエラーメッセージは実行シェル及び有効オプションに強く依存します。分かりやすい組み合わせもあれば、分かりにくい組み合わせもあります。限定的な条件でしか使えない脆いハックのせいで将来消耗するのは割に合いません。本当にやめましょう。
おまけ
今回の例題はとあるプルリクエスト由来だったんですが、指摘したところその人は負けじと以下のスクリプトで変換してきました。
export $(awk -F= '$0=$1"=\""$2"\""' .env)
もちろん無理ですね。やっぱり諦めましょう。
including_eq=hello=world
including_double_quote=hello" world
他にも以下で試す人などがいるようですが、同様に不可能です。諦めてください。
set -o allexport
export .env
set +o allexport
Discussion
この記事を読んでシェルスクリプトに
.env
ファイルを安全に正しく読み込むツールが存在しないことに気づいたので shdotenv というツールを作りました。Docker の.env
だけでなくその他の形式にも対応しています。また shdotenv の標準の.env
形式はシェルスクリプトのサブセットとして定義しているのでシェルスクリプトと互換性があります。たった一行で正しく .env をシェルスクリプトに読み込む方法(と .env の仕様について)