繁体   English   中英

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

[英]Why is putenv() needed on an already defined environment variable?

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

如果使用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 我已经尝试了EGPCSGPCS ,并且当E不存在时,没有按预期填充$_ENV ,但这不会改变getenv()的结果,如文档所示 ,或者显然是stdlib的getenv()的结果内部扩展。


使用pgsql模块演示问题 它建立在用C编写的libpq共享库之上,它在一些可选的PG*环境变量上调用getenv()

在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

原因是这样的:

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]没有。

现在,“hack”也是一个简单的: putenv()[PHP] ,将给定的键/值存储在正在运行的进程的环境中,这就是为什么以后可以通过getenv()[c]找到它的原因。 。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM