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

时间:2017-02-21 23:16:38

标签: php environment-variables getenv

编辑:据我所知,我的问题是因为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"));

如你所见:

  1. getenv成功读取现有值
  2. putenv函数返回true,表示成功,
  3. 实际上没有设置新值,这令人难以置信。
  4. 我是否误解了putenv函数的用途是什么? setenv手册页上是否有一些缺少的文档?如何使用putenv()更新现有的环境变量?

1 个答案:

答案 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_ENVputenv / 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";
}