为什么putenv()需要已经定义的环境变量?

时间:2015-04-17 13:37:21

标签: php apache postgresql environment-variables

php用作apache模块时,来自apache SetEnv指令的环境变量可用于php的getenv(),但它似乎不是通过stdlib的C可用于getenv()个扩展程序。至少它发生在pgsql模块。

如果使用php代码重新实现变量:

putenv("varname=".getenv("varname"));

然后它可用于扩展程序的代码。

问题:为什么需要重新实施?核心php环境与“标准”(stdlib)环境有何区别?

这发生在Ubuntu 12.04中的PHP Version 5.3.10-1ubuntu3.17,作为apache模块。从命令行运行时,不需要上述解决方法。 从另一个问题:Using .pgpass from Apache libphp5.so似乎这个解决方法对于FreeBSD下的php-5.4也是必要的,因此它不仅仅是Ubuntu或php-5.3。

它不依赖于variables_order中包含E的内容。我已经尝试了EGPCSGPCS,并且$_ENV未按预期填充E,但这并未改变{getenv()的结果1}},作为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.

所以尽管在环境中,PGHOST会被忽略。

第二次尝试,现在再次将PGHOST放入环境中,即使它已经存在:

$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

1 个答案:

答案 0 :(得分:8)

原因是:

getenv()[PHP](php函数)获得的环境值与使用getenv()[C](C lib函数)查询的环境不同。 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]没有。

现在,&#34; hack&#34;也是一个简单的:putenv()[PHP],将给定的键/值存储在正在运行的进程的环境中,这就是getenv()[c]稍后可以找到它的原因。