编辑:据我所知,我的问题是因为PHP存在缺陷。我已将此问题复制到PHP错误跟踪器:https://bugs.php.net/bug.php?id=74143并计划尝试实施修复。
putenv函数设置环境变量的值。根据手册,putenv在成功时返回true,在失败时返回false。
但是,我发现putenv函数有时会在不更新当前会话的环境变量的情况下返回true。
要重现此问题,请使用PHP FPM在web服务器中使用fastcgi_param指令设置环境变量。这非常有用,因为它允许将环境变量与同一服务器上的其他主机隔离设置。
示例nginx.conf:
var meh = "{orderid:996553,workorder:996553.010,shipped:000000001,received:000000001,status:GOOD},\
{orderid:996554,workorder:996554.010,shipped:000000001,received:000000001,status:GOOD},\
{orderid:999290,workorder:999290.010,shipped:000000001,received:000000001,status:GOOD},\
{orderid:999290,workorder:999290.020,shipped:000000001,received:000000001,status:GOOD},\
{orderid:999290,workorder:999290.030,shipped:000000001,received:000000001,status:GOOD},\
{orderid:999290,workorder:999290.040,shipped:000000001,received:000000001,status:GOOD},\
{orderid:999290,workorder:999290.050,shipped:000000001,received:000000001,status:GOOD},";
meh = "[" + // enclose with []
meh.replace(/(\w+)(?=:)/g, '"$1"') // search for words followed by a colon
.replace(/,$/, '') // trim the ending comma
.replace(/:([\w.]+)/g, function(match, value){ // grab the values
return ':' + ( // ensure preceding colon is in place
isNaN(value) || value % 1 !== 0 ? // is it a non-float number?
'"' + value + '"' : // enclose with "" if not a non-float number
parseFloat(value) // parse if is number
);
})
+ "]"; // enclose with []
console.log(JSON.parse(meh));
示例test.php:
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"));
如你所见:
我是否误解了putenv函数的用途是什么? setenv手册页上是否有一些缺少的文档?如何使用putenv()更新现有的环境变量?
答案 0 :(得分:4)
这很有趣。经过调查,我发现getenv()
有一个undocumented parameter。
调用putenv("TESTVAR_ENV=new-value")
后跟getenv("TESTVAR_ENV", true)
按预期方式返回new-value
。但是,getenv("TESTVAR_ENV", true)
在调用时返回false,而不首先显式设置值。
从source读取似乎如果 local_only 设置为false(默认值),则使用sapi_getenv
获取值,而使用 local_only < / em>设置为true,使用原生getenv
。
此外,如果sapi_getenv
未返回值,则getenv
将被称为后备。这意味着如果您没有在nginx / Apache配置中设置TESTVAR_ENV
,putenv
/ getenv
将按预期工作。
所以回顾一下:
getenv(name)
从SAPI(php-fpm)内部环境表中搜索,如果未设置变量,则回退到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";
}