当 php
用作 apache
模块,来自 apache 的环境变量 SetEnv
指令可用于 php 的 getenv()
, 但它似乎不适用于 C
通过 stdlib 的 getenv()
扩展.至少它发生在 pgsql
上模块。
如果用php代码重新实例化变量:
putenv("varname=".getenv("varname"));
然后它就可以用于扩展的代码。
问题:为什么需要重新实例化?核心 php 环境与“标准”(stdlib
)环境有何不同?
这发生在:PHP Version 5.3.10-1ubuntu3.17
在 Ubuntu 12.04 中,作为 apache 模块。从命令行运行时,不需要上述解决方法。
来自另一个问题:Using .pgpass from Apache libphp5.so看来这个解决方法对于 FreeBSD 下的 php-5.4 也是必需的,所以它不仅仅是 Ubuntu 或 php-5.3。
它不依赖于variables_order
有E
在里面。我都试过了 EGPCS
和 GPCS
, 和 $_ENV
E
时未填充正如预期的那样不存在,但这不会改变 getenv()
的结果, 作为 documented ,或者显然是 stdlib 的 getenv()
的结果来自内部扩展。
问题演示 pgsql
模块。它建立在 libpq
之上用 C
编写的共享库,它调用 getenv()
在少数可选 PG*
环境变量。
在apache配置文件中,在一个<VirtualHost>
下,我将其设置为使连接尝试失败:
SetEnv PGHOST doesnotexist
并且没有在 pg_connect
中指定主机打电话,所以PGHOST
在场时必须带走。
第一次尝试:
$v=getenv("PGHOST");
echo "PGHOST=$v\n";
$cnx=pg_connect("user=daniel");
if ($cnx) {
echo "Connection is successful.";
}
结果:
PGHOST=doesnotexist Connection is successful.
So PGHOST
is getting ignored, despite being in the environment.
Second try, now putting again PGHOST
into the environment even though it's already there:
$v=getenv("PGHOST");
echo "PGHOST=$v\n";
putenv("PGHOST=".getenv("PGHOST"));
$cnx=pg_connect("user=daniel");
if ($cnx) {
echo "Connection is successful.";
}
结果(未能连接到指定主机,如预期):
PGHOST=doesnotexist Warning: pg_connect(): Unable to connect to PostgreSQL server: could not translate host name "doesnotexist" to address: Name or service not known in /var/www/test/pgtest2.php on line 8
最佳答案
原因是这样的:
您从 getenv()[PHP]
(php 函数)获得的环境值与您使用 getenv()[C]
(the C库函数)。 getenv()[PHP]
所做的是检查已注册的 sapi 是否匹配( http://lxr.php.net/xref/PHP_5_6/ext/standard/basic_functions.c#3999 )。
apache2 sapi 通过自己的环境上下文 (http://lxr.php.net/xref/PHP_5_6/sapi/apache2handler/sapi_apache2.c#253) 执行此操作,而不是来自 apache 进程本身的标准操作系统环境。
只有当没有找到匹配时,它才会检查实际进程的环境。所以这就是为什么 getenv()[PHP]
返回一个值,而 getenv()[C]
没有。
现在,“hack”也很简单:putenv()[PHP]
,将给定的键/值存储在运行进程的环境中,这就是为什么它可以稍后由 getenv()[c]
找到。
关于php - 为什么已经定义的环境变量需要 putenv()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29700814/