When php
is used as an apache
module, an environment variable coming from an apache SetEnv
directive is available to php's getenv()
, but it does not appear to be available to C
extensions through stdlib's getenv()
. At least it happens with the pgsql
module.
当php用作apache模块时,来自apache SetEnv指令的环境变量可用于php的getenv(),但它似乎不能通过stdlib的getenv()用于C扩展。至少它发生在pgsql模块中。
If the variable is reinstantiated with the php code:
如果使用php代码重新实现变量:
putenv("varname=".getenv("varname"));
then it becomes available to the extension's code.
然后它可用于扩展程序的代码。
The question: why is that reinstantiation necessary? How is the core php environment distinct from the "standard" (stdlib
) environment?
问题:为什么需要重新实施?核心php环境与“标准”(stdlib)环境有何区别?
This occurs with: PHP Version 5.3.10-1ubuntu3.17
in Ubuntu 12.04, as an apache module. When run from the command line, the above workaround is not necessary. From this other question: Using .pgpass from Apache libphp5.so it appears that this workaround is also necessary for php-5.4 under FreeBSD so it's not just Ubuntu or php-5.3.
这种情况发生在:Ubuntu 12.04中的PHP版本5.3.10-1ubuntu3.17,作为apache模块。从命令行运行时,不需要上述解决方法。从另一个问题:在Apache libphp5中使用.pgpass。因此看起来这个解决方法对于FreeBSD下的php-5.4也是必需的,所以它不仅仅是Ubuntu或php-5.3。
It doesn't depend on variables_order
having E
in it. I've tried both EGPCS
and GPCS
, and $_ENV
is not populated when E
is not there, as expected, but that doesn't change the result of getenv()
, as documented, or apparently the result of stdlib's getenv()
from inside extensions.
它不依赖于其中包含E的variables_order。我已经尝试了EGPCS和GPCS,并且当E不存在时,没有按预期填充$ _ENV,但这不会改变getenv()的结果,如文档所示,或者显然是stdlib的getenv()的结果内部扩展。
Demo of the problem with the pgsql
module. It's built on top of the libpq
shared library written in C
, which calls getenv()
on a handful of optional PG*
environment variables.
使用pgsql模块演示问题。它建立在用C编写的libpq共享库之上,它在一些可选的PG *环境变量上调用getenv()。
In apache configuration file, under a <VirtualHost>
, I'm setting this to make connection attempts fail:
在apache配置文件中,在
SetEnv PGHOST doesnotexist
and not specifying a host in the pg_connect
call, so PGHOST
must be taken when present.
并且没有在pg_connect调用中指定主机,因此必须在存在时使用PGHOST。
First try:
第一次尝试:
$v=getenv("PGHOST");
echo "PGHOST=$v\n";
$cnx=pg_connect("user=daniel");
if ($cnx) {
echo "Connection is successful.";
}
Result:
结果:
PGHOST=doesnotexist Connection is successful.
So PGHOST
is getting ignored, despite being in the environment.
因此,尽管身处环境中,PGHOST仍会被忽视。
Second try, now putting again PGHOST
into the environment even though it's already there:
第二次尝试,现在再次将PGHOST放入环境中,即使它已经存在:
$v=getenv("PGHOST");
echo "PGHOST=$v\n";
putenv("PGHOST=".getenv("PGHOST"));
$cnx=pg_connect("user=daniel");
if ($cnx) {
echo "Connection is successful.";
}
Result (failure to connect to the specified host, as expected):
结果(无法按预期连接到指定的主机):
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 个解决方案
#1
8
The reason is this:
原因是这样的:
The environment values you get from getenv()[PHP]
(the php function) are different than the environment you query with getenv()[C]
(the C lib function). What getenv()[PHP]
does, is checking with the registered sapi for a match (http://lxr.php.net/xref/PHP_5_6/ext/standard/basic_functions.c#3999).
从getenv()[PHP](php函数)获得的环境值与使用getenv()[C](C lib函数)查询的环境不同。 getenv()[PHP]的作用是使用已注册的sapi进行匹配检查(http://lxr.php.net/xref/PHP_5_6/ext/standard/basic_functions.c#3999)。
The apache2 sapi does this through its own environment context (http://lxr.php.net/xref/PHP_5_6/sapi/apache2handler/sapi_apache2.c#253), not the standard OS environment from the apache process itself.
apache2 sapi通过自己的环境上下文(http://lxr.php.net/xref/PHP_5_6/sapi/apache2handler/sapi_apache2.c#253)完成此操作,而不是来自apache进程本身的标准操作系统环境。
ONLY when there is no match found, it will check at the environment of the actual process. So this is why getenv()[PHP]
returns a value, but getenv()[C]
does not.
只有在找不到匹配项时,它才会检查实际过程的环境。所以这就是为什么getenv()[PHP]返回一个值,但是getenv()[C]没有。
Now, the "hack" is a simple one as well: putenv()[PHP]
, stores the given key/value in the environment of the running process, which is why it can be found later on by getenv()[c]
.
现在,“hack”也是一个简单的:putenv()[PHP],将给定的键/值存储在正在运行的进程的环境中,这就是为什么以后可以通过getenv()[c]找到它的原因。 。
#1
8
The reason is this:
原因是这样的:
The environment values you get from getenv()[PHP]
(the php function) are different than the environment you query with getenv()[C]
(the C lib function). What getenv()[PHP]
does, is checking with the registered sapi for a match (http://lxr.php.net/xref/PHP_5_6/ext/standard/basic_functions.c#3999).
从getenv()[PHP](php函数)获得的环境值与使用getenv()[C](C lib函数)查询的环境不同。 getenv()[PHP]的作用是使用已注册的sapi进行匹配检查(http://lxr.php.net/xref/PHP_5_6/ext/standard/basic_functions.c#3999)。
The apache2 sapi does this through its own environment context (http://lxr.php.net/xref/PHP_5_6/sapi/apache2handler/sapi_apache2.c#253), not the standard OS environment from the apache process itself.
apache2 sapi通过自己的环境上下文(http://lxr.php.net/xref/PHP_5_6/sapi/apache2handler/sapi_apache2.c#253)完成此操作,而不是来自apache进程本身的标准操作系统环境。
ONLY when there is no match found, it will check at the environment of the actual process. So this is why getenv()[PHP]
returns a value, but getenv()[C]
does not.
只有在找不到匹配项时,它才会检查实际过程的环境。所以这就是为什么getenv()[PHP]返回一个值,但是getenv()[C]没有。
Now, the "hack" is a simple one as well: putenv()[PHP]
, stores the given key/value in the environment of the running process, which is why it can be found later on by getenv()[c]
.
现在,“hack”也是一个简单的:putenv()[PHP],将给定的键/值存储在正在运行的进程的环境中,这就是为什么以后可以通过getenv()[c]找到它的原因。 。