Unengineered Weblog

PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND

Bash が環境変数を勝手に変えてくる!

ネタバレ

犯人は BASH_ENV

私がシェルスクリプトを書いていたとき、 bash が勝手に環境変数を変えてくるという謎の挙動をした。なぜなのか調べた。

どんなことが起こったのか

私が書いていたシェルスクリプトは複雑で本題とは関係ない。話を簡単にするために、次のシェルスクリプト hello を書いていたとしよう。 環境変数 NAME へ挨拶するスクリプトだ。

#!/bin/bash
echo "hello, $NAME"

そして次のように実行した。すると意図しない挙動をする。

$ NAME=alice ./hello
hello, bob
🤔

環境変数 NAME は alice だったはず! なぜ bash環境変数を勝手に変えてくるのだろうか。

状況はどうであったか

このシェルの環境変数を見てみると怪しいものがある。

$ printenv
...
BASH_ENV=/path/to/name
....

そして気になる /path/to/name の中身は次の通り。

NAME=bob

BASH_ENV とは

BASH_ENV

If this variable is set when Bash is invoked to execute a shell script, its value is expanded and used as the name of a startup file to read before executing the script.

www.gnu.org

環境変数 BASH_ENV がセットしていたとき、bash スクリプトが実行されると、スクリプトが実行される前にファイル BASH_ENV が読まれるそうだ。

つまり、上の name スクリプトは /path/to/name によって環境変数 NAME が上書きされてしまったのである。

BASH_ENV を unset したら意図した挙動になった。

$ unset BASH_ENV
$ NAME=alice ./hello
hello, alice

なぜ BASH_ENV がセットされていたのか

ある GitHub リポジトリにあった Dockerfile で BASH_ENV が使われていたのをよくわからずにコピペして動かしていたから。よくわからないものをコピペして動かすのはよくないね。