環境変数のサイズやPATHの長さ制限に注意:Tech TIPS(1/2 ページ)
いくつかの理由により、Windows OSで利用できる環境変数のサイズやPATHの長さには制限がある。その制限と回避方法などについて解説する。
対象OS:Windows 7/Windows 8/Windows 8.1/Windows 10/Windows Server 2008/Windows Server 2008 R2/Windows Server 2012/Windows Server 2012 R2
解説
コマンドプロンプト上でコマンドを実行する場合、入力されたコマンド名がフルパス名で指定されていなければ、PATH環境変数で指定されている各フォルダーからコマンドが検索され、実行される。
Windows OSをインストールした直後のPATH環境変数には、%SystemRoot%以下のいくつかのフォルダーしか登録されておらず、非常にシンプルな内容になっている。
※Windows 10 Proのインストール直後のデフォルトのPATH環境変数の内容例。非常にシンプルである
C:\>path
PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\
C:\>
だが多くのアプリケーションをインストールしたり、システムの更新などを繰り返したりしていると、実行ファイルや関連するデータファイルなどがさまざまな場所に配置されていく。結果としてPATHやそれ以外の環境変数の総数やサイズがどんどん増えてくる。
実は環境変数のサイズには制限があり、これが問題を引き起こすことがある。
一番表面化しやすい問題は、PATH環境変数の値が長くなりすぎていくつかのパスがカットされ、コマンドを見つけられなくなる、という不具合だろう。Windows OSのエディションなどにもよるが、ほとんどの場合はPATH環境変数の最大長は約2000文字以下に制限されている。これを超えるようなPATH文字列を設定しても途中で切り捨てられてしまう。
本記事では、Windows OSにおける環境変数の仕組みとその制限、回避方法などについてまとめておく。
コマンドプロンプトの操作方法が分からない場合は、TIPS「これだけは覚えておきたいWindowsのコマンドプロンプトの使い方」を参照していただきたい。
●環境変数のサイズ制限1:内部的には、変数ごとに約3万2000文字まで利用可能
Windows OSにおける環境変数とは、変数の「名前」とその「値」を文字列を組にして(「VAR=VALUE」のようにする)、さらにそれらをひとまとめにしたもの(=「環境変数ブロック」と言う)のことである。コマンドプロンプト上で「set」コマンドを実行すると、その一覧が表示される。
C:\>set ……全環境変数を表示させるコマンド
ALLUSERSPROFILE=C:\ProgramData
APPDATA=C:\Users\user01\AppData\Roaming
……(中略)……
USERPROFILE=C:\Users\user01
windir=C:\Windows
C:\>
この環境変数(の集合体)はWindows OSの「プロセス」ごとに固有の情報であり、その初期値は、親プロセスの環境変数の内容を全て引き継いだものである。子プロセス内で環境変数の内容を変更しても、それは親プロセスへは伝達されない。
環境変数には、「1つの変数当たり最大32,767文字まで」(Unicodeなので、バイト数で言えば最大64Kbytesまで)という制限がある。一方、全ての環境変数を合計したサイズ(環境変数ブロックの最大サイズ)は、OSの技術的には特に制限はなく、利用可能なメモリサイズで制限される。ただしWindows XPなどの古いOSでは総サイズが最大32,767文字までに制限されていた。
- 「Environment Variables」[英語](マイクロソフトMSDNサイト)
●環境変数のサイズ制限2:コマンドプロンプトの入力行は約8000文字まで
環境変数を設定するには、コマンドプロンプトで例えば「set var1=C:\Windows」のようにして実行する。だがコマンドプロンプトでは1行当たり「最大で8190文字しか入力できない」ので、これを超えるような長いsetコマンドは実行できない。
行の先頭には「set <変数名>=」というコマンド文字列も必要なので、結局コマンドプロンプト上で設定可能な環境変数のサイズは、最長でも約8180文字程度に制限されることになる。
別の長い環境変数(への参照)を組み合わせて、例えば「set var=%longvar1%;%longvar2%;%longvar3%」のようにして8000文字を超えさせようとしてもエラーとなる。コマンドライン中の環境変数を展開した時点で内部の作業用バッファーが溢れるからである。環境変数の「展開後」のサイズが8000文字を超えるようなコマンドも実行できない。
※約8000文字がセットされている3つの環境変数を組み合わせようとした場合の例
C:\>set var=%longvar1%;%longvar2%;%longvar3% ……変数の参照を使って、8000文字を超えるような長いコマンドを実行させてみる
入力行が長すぎます。 ……変数の展開に失敗したので実行できない
C:\>
●環境変数のサイズ制限3:システム環境変数やユーザー環境変数の最大値は約2000文字まで
環境変数は親プロセスから継承される。それでは最初のプロセス(各ユーザーのルートとなるプロセス)の環境変数はどうなっているかというと、これには以下の2つの初期値が用意されている。
タイプ | 意味 |
---|---|
システム環境変数 | ・システム全体で使われる共通の環境変数 ・全ユーザーで共通 ・実際の環境変数の設定は、レジストリのHKEY_LOCAL_MACHINEの \SYSTEM\CurrentControlSet\Control\Session Manager\Environmentに格納されている |
ユーザー環境変数 | ・システムにユーザーがサインイン(ログオン)するたびに設定される環境変数 ・ユーザーごとに固有 ・最初にシステム環境が設定され、その後さらにユーザー環境変数の値が設定される ・実際の環境変数の設定は、レジストリのHKEY_CURRENT_USERの\Environmentに格納されている |
環境変数の初期値と格納場所 |
各ユーザーの環境変数には、これら2つの初期値を合成したものが設定される。ユーザーがシステムにサインインすると、まず「システム環境変数」がユーザーのルートとなるプロセスに設定される。その後、さらに「ユーザー環境変数」の値が設定されるので、最終的には2種類の環境変数の値を全て合成したものが設定されることになる。
ただし「PATH」環境変数については特別な処理が行われる。最初にシステム環境変数のPATHの値が設定された後、ユーザー環境変数側のPATHの値が「;」で区切って「追加」されるようになっている。これにより、システム全体で共通のPATH設定をベースにして、ユーザーごとの独自のコマンドパスも簡単に追加できるようになっている。
システム環境変数とユーザー環境変数は、「システムのプロパティ」画面やsetxコマンドを使って設定することができる(ただしsetxコマンドでは変数の値として最大1024文字までしか設定できない。それ以上の長い文字列は切り捨てられる)。具体的な設定方法については次のTIPSを参照していただきたい。
- TIPS「環境変数を変更する」
- TIPS「setxで環境変数の値を設定する」
環境変数の設定
環境変数の初期値は、「システムのプロパティ」画面で確認、設定できる。この画面を出すには、「コンピューター」や「PC」アイコンを右クリックするか、Windows 8以降なら[Windows]+[X]キーで[システム]を選択してコントロールパネルの「システム」を表示させ、左側のメニューから[システムの詳細設定]のリンクをクリックする。
(1)「システムのプロパティ」画面を表示させる。
(2)[詳細設定]タブを選択する。
(3)[環境変数]ボタンをクリックする。
(4)上側がユーザーごとの環境変数。サインイン(ログオン)したユーザー固有の情報。システム環境変数の設定後に、こちらの環境変数の初期化が行われる。
(5)下側がシステム全体で共通の環境変数。最初にシステムが起動したときに設定される。
(6)TMPやTEMPは一時データ保存用のフォルダー。システム環境変数側にもTMPやTEMPがある。このように同じ名前の環境変数が両方にある場合は、ユーザー環境変数によって値が上書き設定される。
(7)環境変数の値。ここに設定できる文字列の長さには制限がある。
これらの画面では、環境変数の初期値を設定できる。ただし、ここで設定できる環境変数は、「最大でも2047文字まで」に制限されている(変数の値欄には2048文字以上入力できない)。
そのため、システムの初期値として設定できるPATHは、システム環境変数PATHの約2000文字とユーザー環境変数PATHの約2000文字を加えた、約4000文字までとなる。実際の運用では、システム環境変数のPATHがメインで、ユーザー環境変数のPATHは補助的にしか使わないだろうから、システムのプロパティ画面で設定できるPATHの最大長は(システム環境変数のPATHによる)約2000文字までと考えておけばよいだろう。
■[補足1]環境変数の参照を使った値の指定
上の画面で環境変数の値を入力する場合、例えば「C:\MyProgram;D:\MyTools」のように直接フルパスを記述するだけでなく、「%myprg%;%mytool%」のように、別の環境変数を参照するような文字列を設定することもできる(myprgやmytoolも環境変数として定義しておくこと)。このような表記が使われている場合は、システムが最初に環境変数を評価する時(最初に環境変数ブロックを作成する時)に展開される。こうすると短い文字列でより長い値を表現できるので(一種の間接参照になる)、値としては2000文字しか入力できなくても、最終的な環境変数の値は、もっと長いパス文字列にできる。
ただしこの方法を使っても、最終的に展開される結果の文字列の長さは最大で8190文字程度までに制限されるようである(制限を超えると途中で文字列が強制的にカットされる。場合によっては隣の環境変数とくっついてしまって、検索が正しく行えなくなることがあるので注意)。また、この環境変数の参照の展開処理は最初に1回しか行われない。例えば最終的なPATHの中に%myvar%のような文字列が入っていた場合、コマンドの実行時にこれが動的に展開されることはないし、myvarの指す先のフォルダーからコマンドが検索されることもない。
■[補足2]ユーザー環境変数からシステム環境変数を参照する
もしシステム環境変数とユーザー環境変数に同じ名前の変数があった場合は(PATH変数以外)、後者のもので上書き設定されるので、ユーザー環境変数の設定内容が優先されることになる。PATH変数のように、システム環境変数の内容を引き継いだまま、別の値を追加したいなら、例えば「%var%;c:\newpath」のようにすればよい(VARという名前の変数が両方にある場合)。こうすれば、最初にシステム環境変数のVARの値がセットされた後、その末尾に「c:\newpath」が追加される。
●結論:最終的なPATHの制限は約2000文字と想定すべき
以上、環境変数の値(文字列)の長さを制約する3つの制限についてみてきた。これら3つの要件を満たすことを考えると、安全に利用可能なPATHの最大長は約2000文字と想定しておくべきだろう。
システム環境変数のPATHとユーザー環境変数のPATHは別のものなので、必要なPATH文字列をこの2つの環境変数にうまく割り振ったり、%var%のような間接的な参照表記を使ったりすれば、もっと長いPATHが利用できる。
だが、このような細工はトラブルの元となるのでおすすめできない。特にシステム環境変数のPATHは、アプリケーションのインストーラーなどが操作することも多いので、知らないうちに変更されていることが多く、不用意にいじるべきではない。
Copyright© Digital Advantage Corp. All Rights Reserved.