当php
用作apache
模块时,来自apache SetEnv
指令的环境variables可用于php的getenv()
,但是它似乎不能通过stdlib的getenv()
用于C
扩展。 至less它发生在pgsql
模块上。
如果variables重新用php代码实现:
putenv("varname=".getenv("varname"));
那么它可以被扩展的代码使用。
问题:为什么必须重新实施? 核心php环境与“标准”( stdlib
)环境有什么不同?
这发生在:Ubuntu 12.04中的PHP Version 5.3.10-1ubuntu3.17
,作为apache模块。 从命令行运行时,上述解决方法不是必需的。 从另一个问题: 使用Apache libphp5.so中的.pgpass看起来这个解决方法对于FreeBSD下的php-5.4也是必须的,所以它不仅仅是Ubuntu或者php-5.3。
它不依赖于具有E
variables_order
。 我已经尝试了EGPCS
和GPCS
,并且当E
不在那里时, $_ENV
没有被填充,但是这不会像logging的那样改变getenv()
的结果,或者显然是从stdlib的getenv()
内部扩展。
演示与pgsql
模块的问题 。 它build立在用C
编写的libpq
共享库之上,它在几个可选的PG*
环境variables上调用getenv()
。
在apacheconfiguration文件中,在<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 连接成功。
所以尽pipe处于环境中, PGHOST
也被忽略了。
第二次尝试 ,现在再次把PGHOST
放到环境中,尽pipe它已经在那里了:
$v=getenv("PGHOST"); echo "PGHOST=$v\n"; putenv("PGHOST=".getenv("PGHOST")); $cnx=pg_connect("user=daniel"); if ($cnx) { echo "Connection is successful."; }
结果(按预期未能连接到指定的主机):
PGHOST = doesnotexist 警告:pg_connect():无法连接到PostgreSQL服务器: 无法翻译主机名“doesnotexist”来解决: 在第8行的/var/www/test/pgtest2.php中未知的名称或服务
原因是这样的:
您从getenv()[PHP]
(php函数)获得的环境值与使用getenv()[C]
(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]
: putenv()[PHP]
将给定的键/值存储在正在运行的进程的环境中,这就是为什么后面可以通过getenv()[c]
。