如何使用putenv()更新现有环境变量?

Gre*_*reg 13 php environment-variables getenv

编辑:据我所知,我的问题是因为PHP存在缺陷.我在这里将这个问题复制到PHP bug跟踪器:https://bugs.php.net/bug.php?id = 74143并计划尝试实现修复.


putenv函数设置环境变量的值.根据手册,putenv在成功时返回true,在失败时返回false.

但是,我发现putenv函数有时会返回true而不更新当前会话的环境变量.

要重现此问题,请使用PHP FPM在Web服务器中使用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;
}
Run Code Online (Sandbox Code Playgroud)

示例test.php:

var_dump(getenv("TESTVAR_ENV"));
var_dump(putenv("TESTVAR_ENV=new-value"));
var_dump(getenv("TESTVAR_ENV"));
Run Code Online (Sandbox Code Playgroud)

test.php的输出:

string(12) "old-value"
bool(true)
string(12) "old-value"
Run Code Online (Sandbox Code Playgroud)

如你看到的:

  1. getenv成功读取现有值,
  2. putenv函数返回true,表示成功,
  3. 实际上没有设置新值,这令人难以置信.

我误解了putenv函数的用途是什么?setenv手册页上是否有一些缺少的文档?如何使用putenv()更新现有环境变量?

Joe*_*Joe 5

这很有趣。经过调查,我发现有一个未公开的参数进行getenv()

调用putenv("TESTVAR_ENV=new-value")后按预期getenv("TESTVAR_ENV", true)返回new-value。但是,getenv("TESTVAR_ENV", true)在未先显式设置值的情况下调用时返回 false。

源代码中读取似乎如果local_only设置为 false(默认值),则使用 获取值sapi_getenv,而local_only设置为 truegetenv则使用本机。

此外,如果sapi_getenv不返回值,则getenv称为回退。意思是,如果您根本没有TESTVAR_ENV在 nginx/Apache 配置中进行设置,putenv/ 会getenv按预期工作。

所以回顾一下:

  • getenv(name) 从 SAPI 的 (php-fpm) 内部环境表中搜索,如果未设置变量,则回退到操作系统的环境。
  • getenv(name, true) 仅从操作系统的环境中搜索,它不一定(取决于 SAPI)包含在 Web 服务器配置中注册的变量。
  • putenv() 始终只更新操作系统的环境。

我使用以下内容对此进行了测试:

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";
}
Run Code Online (Sandbox Code Playgroud)