web-dev-qa-db-ja.com

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

編集:私の知る限り、私の質問はPHPの欠陥が原因です。この質問をPHPバグトラッカーここにコピーします https://bugs.php.net/bug.php?id=7414 にコピーして、修正を実装します。


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

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

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

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()を使用して既存の環境変数を更新するにはどうすればよいですか?

13
Greg

これは面白い。調査したところ、getenv()ドキュメント化されていないパラメーター があることがわかりました。

putenv("TESTVAR_ENV=new-value")に続いてgetenv("TESTVAR_ENV", true)を呼び出すと、期待どおりに_new-value_が返されます。ただし、最初に値を明示的に設定せずにgetenv("TESTVAR_ENV", true)を呼び出すと、falseが返されます。

source から読み取ると、local_onlyがfalse(デフォルト)に設定されている場合、値は_sapi_getenv_、local_onlyをtrueに設定すると、ネイティブのgetenvが使用されます。

さらに、_sapi_getenv_が値を返さない場合、getenvがフォールバックとして呼び出されます。 nginx/Apache構成で_TESTVAR_ENV_をまったく設定しない場合、putenv/getenvは期待どおりに機能します。

要約すると:

  • getenv(name)は、SAPI(php-fpm)内部環境テーブルから検索し、変数が設定されていない場合はOSの環境にフォールバックします。
  • getenv(name, true)は、OSの環境からのみ検索します。これには、(SAPIに応じて)Webサーバーの構成に登録された変数が含まれているとは限りません。
  • 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";
}
_
4
Joe