[英]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
。 我已經嘗試了EGPCS
和GPCS
,並且當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.