「登場人物」と「誰が誰と何をしているか」の理解を重視します。
環境変数とは
その名のとおり、環境が使う変数。
環境とは
環境 とは、プログラムが動作する何らかの単位のこと。
英語では Environment と書く。Env と略すことが多い。
以下を全部含む。
- 1 コマンドやスクリプト
- 2 アプリ
- 3 ミドルウェア
- 4 PC、サーバー、コンテナ、仮想マシン、インスタンスといった「一台」分
- 5 n台のサーバーと、その他ネットワークなどインフラを含んだシステム全体
ただし、この文脈では 4 以前を指す。
変数とは
変数 とは、何らかの情報を入れておくもののこと。
英語では Variable と書く。Var などと略すことがある。
変数には名前(変数名)と情報(値)があり、名前に対して情報を入れる、という書き方をする。
JAVA_HOME=D:\languages\java\jdk-17.0.7
これは JAVA_HOME
という名前の変数に、D:\languages\java\jdk-17.0.7
という情報を入れている。これを表現すると、次のようになる
- 変数名 JAVA_HOME の変数に、
- D:\languages\java\jdk-17.0.7 という値を入れている
同様に、特定の情報を取り出すときも、変数名を指定すると、その変数名(が持つ値)が届けられる。
これはコンピュータ上の基本的な仕組みであり、そういうものと受け入れるしかない。数学で使う数式とは違うが、数学は無視していい。var1=xxx
と書いたら、これはvar1にxxxという情報を入れます、という意味なのだ。
環境変数とは
環境が使う変数である。
コマンドやスクリプトも、アプリも、ミドルウェアも、またまたサーバーなど「1台のコンピュータ」も、どれも 環境変数という情報源を使えるようになっている。そういう仕組みだ。
情報を持たせたり書き換えたりする仕組みは色々あるが、環境変数もその一種となる。特に環境変数はそれら環境とは独立した機構であるため、環境も、環境を使う私たち自身も、自由に環境変数にアクセスできる。
以下はイメージ。
たとえば以下のような使い方をする。
- 1: アプリの挙動を設定に応じて変えられるようにしておく
- 2: その設定は、環境変数 XXX から読み込むようにする
- 2: アプリの開発者は、状況に応じて XXX の値を書き換えてからアプリを起動する
こうすれば アプリ自体に手を加えることなく、設定を(環境変数 XXX 経由で)変えるだけでアプリの挙動を変えられる。バカ真面目に「挙動を変えたいのでアプリを作り直します」なんてしなくてもいいわけだ。
環境変数の細かい性質
ここからもう少し細かい仕組みや制約の話に入る。
環境変数は「いつ」読み込まれるのか
これは単純で、環境を起動したとき である。
しかし、段階的である。詳しく見ていく。
まずサーバーの単位(厳密には OS)では、起動時にすべての環境変数を読み込む。というより 環境変数という仕組みは OS の機能 なので、OS を起動したときに使えるようになるのはまあ当然である。
次に、各種プログラム(スクリプトもアプリもミドルウェアも全部含む)は、起動した時点 での環境変数の値を コピーして保持する。以下のイメージ。このアプリは起動して一度読み込んだ後は、2: のコピーの方を見る。
なのでアプリから環境変数 abc や def を書き換えても、元の 1: の方は汚されない。コピーしたものなのでご自由に使えばいい。情報を保存する手段として環境変数を使うことは通常しない。とはいえ、環境変数は、あくまでも起動時に外から設定を取ってくるためのものである。起動時にコピーを保持できれば十分だ。
で、ここからがややこしいのだが、アプリからさらに別のプログラムを起動するとしよう。スクリプトを実行するでもいいし、別のアプリ2を起動する、でもいい。仮にスクリプトを実行するとしよう。このとき、スクリプトから見える環境変数はどうなっているか。わかりづらいので、アプリ側で abc を 11111 に変えていたとしよう。以下の構図だ。
このとき、スクリプトから見える環境変数はどうなるのか。
答えは 「自分を起動したやつが持っている分」を「コピーして保持する」 である。
これを 伝搬 と呼んだりする。OS の分ではなく、自分を実行したやつ(親)の分をコピーするわけだ。
グローバルとローカル
一般的な話をすると、環境変数のあり方は 2 種類ある。
OS の設定として存在する大本を グローバル という。
アプリやスクリプトなど、各プログラムが持っている分を ローカル という。
ローカルを持ってるけど、グローバルも見れる
ややこしいが、プログラムは自分のローカルの分のみならず、大元のグローバルの分を別途見に行くこともできる。
ただし、上図でバツを示しているとおり、自分を実行した親のローカルを見ることはできない。もっというと、プログラムは自分以外のローカルを見ることができない。
OS レベルでは見れる。アプリのローカルも、スクリプトのローカルも、OS が使える人であれば見ようと思えば見れる。
おわりに
これで環境変数がどこでどうなっているかというイメージは湧いたと思う。