1. ホーム
  2. php

[解決済み] putenv()を使用して既存の環境変数を更新するにはどうすればよいですか?

2022-02-15 23:23:06

質問

編集:私の知る限り、私の質問はPHPの欠陥のためです。この質問をPHPのバグトラッカーにコピーしておきました。 https://bugs.php.net/bug.php?id=74143 で、修正を試みる予定です。


putenv関数は、環境変数の値を設定する関数です。マニュアルによると、putenvは成功するとtrueを返し、失敗するとfalseを返します。

しかし、putenv関数が、現在のセッションの環境変数を更新せずに、trueを返すことがあることに気づきました。

この問題を再現するには、PHP FPM を使用しているウェブサーバーで、 fastcgi_param ディレクティブを使用して環境変数を設定します。これは、同じサーバー上の他のホストと分離して環境変数を設定できるため、非常に便利です。

nginx.confの例。

location ~ \.php$ {
        fastcgi_pass    unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_param   TESTVAR_ENV     old-value;
        include         fastcgi_params;
}

test.phpの例です。

var_dump(getenv("TESTVAR_ENV"));
var_dump(putenv("TESTVAR_ENV=new-value"));
var_dump(getenv("TESTVAR_ENV"));

test.phpの出力。

string(12) "old-value"
bool(true)
string(12) "old-value"

ご覧の通りです。

  1. は、getenvによって既存の値が正常に読み込まれます。
  2. putenv関数は成功を意味するtrueを返します。
  3. が、実際には新しい値が設定されないので、非常に紛らわしいです。

私はputenv関数の目的を誤解しているのでしょうか?setenvのマニュアルページには、何か足りないドキュメントがあるのでしょうか?既存の環境変数を更新するために putenv() を使用するにはどうすればよいのでしょうか?

どのように解決するのですか?

これは面白いですね。調べてみると 文書化されていないパラメータ に対して getenv() .

呼称 putenv("TESTVAR_ENV=new-value") に続いて getenv("TESTVAR_ENV", true) が返ってくる new-value は期待通りです。しかし getenv("TESTVAR_ENV", true) は、最初に明示的に値を設定せずに呼び出すと false を返します。

からの読み込み ソース というのは、もし ローカルのみ を false (デフォルト) に設定すると、その値は sapi_getenv であるのに対し ローカル_オンリー を true に設定すると、ネイティブの getenv が使用されます。

さらに、もし sapi_getenv が値を返さない場合 getenv がフォールバックとして呼び出されます。つまり、もしあなたが TESTVAR_ENV を設定する必要があります。 putenv / getenv は期待通りに動作します。

というわけで、おさらいです。

  • getenv(name) は、SAPI (php-fpm) の内部環境テーブルを検索し、変数が設定されていない場合は OS の環境にフォールバックします。
  • getenv(name, true) は、OS の環境のみから検索します。この環境は、(SAPI に依存しますが) ウェブサーバの設定に登録された変数を必ずしも含んでいるとは限りません。
  • putenv() 常にOSの環境のみを更新します。

試しに下記を使用してみました。

header("Content-Type: text/plain");

dump_env();
echo 'getenv("TESTVAR_ENV") => ' .
    var_export(getenv("TESTVAR_ENV"), true) . "\n";
echo 'getenv("TESTVAR_ENV", true) => ' .
    var_export(getenv("TESTVAR_ENV", true), true) . "\n";
echo "-----------\n";
echo 'putenv("TESTVAR_ENV=new-value") => ' . 
    var_export(putenv("TESTVAR_ENV=new-value"), true) . "\n";
dump_env();
echo 'getenv("TESTVAR_ENV") => ' .
    var_export(getenv("TESTVAR_ENV"), true) . "\n";
echo 'getenv("TESTVAR_ENV", true) => ' .
    var_export(getenv("TESTVAR_ENV", true), true) . "\n";

function dump_env() {
    echo "--- env ---\n" . `env` . "-----------\n";
}