簡體   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