2017-02-21 92 views
8

编辑:据我所知,我的问题是因为PHP的缺陷。我已将此问题复制到PHP错误跟踪器中:https://bugs.php.net/bug.php?id=74143并计划尝试并实施修复。如何使用putenv()更新现有的环境变量?


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. 成功读取现有值,
  2. putenv函数返回true,表示成功,
  3. 新值没有实际设置,这是令人难以置信的混淆。

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

+0

我从来没见过这种行为我自己。您是否尝试先删除旧值? 'putenv(“TESTVAR_ENV”)'应该清除该值,或者可以尝试使用'$ _SERVER'来代替? – miken32

+1

实际上,只是用Nginx和PHP-FPM测试了这个,而不是CLI,我看到了同样的情况。 – miken32

+0

您认为这是PHP还是PHP-FPM的错误? – Greg

回答

2

这很有趣。经过调查,我发现undocumented parametergetenv()

调用putenv("TESTVAR_ENV=new-value")后跟getenv("TESTVAR_ENV", true)如预期的那样返回new-value。但是,getenv("TESTVAR_ENV", true)在未明确设置值的情况下调用时会返回false。

从它看来,如果local_only设置为false(默认值),使用sapi_getenv,而与local_only设置为true,本地getenv使用值是牵强的source阅读。

此外,如果sapi_getenv没有返回值,则getenv被称为回退。这意味着如果您根本没有在nginx/Apache配置中设置TESTVAR_ENV,则putenv/getenv按预期工作。

因此,要回顾:从SAPI的(PHP-FPM)

  • getenv(name)搜索内部环境表,并回退给OS的环境变量,如果没有设置。
  • getenv(name, true)仅从OS环境进行搜索,不一定(取决于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"; 
} 
+0

感谢您对此的意见。我已经更新了php.net上的文档以反映这种行为,但我仍然认为功能可能会有所改进。 – Greg