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

时间:2023-01-06 23:21:27

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]找到它的原因。 。