2017-02-21 91 views
8

編輯:據我所知,我的問題是因爲PHP的缺陷。我已將此問題複製到PHP錯誤跟蹤器中:https://bugs.php.net/bug.php?id=74143並計劃嘗試並實施修復。如何使用putenv()更新現有的環境變量?


putenv函數設置環境變量的值。根據手冊,putenv成功返回true,失敗則返回false。

但是,我發現putenv函數有時會返回true而不更新當前會話的環境變量。

要重現此問題,請使用fastcgi_param指令,使用PHP FPM在Web服務器中設置環境變量。這非常有用,因爲它允許將環境變量隔離設置到同一臺服務器上的其他主機。

例nginx.conf:

location ~ \.php$ { 
     fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; 
     fastcgi_param TESTVAR_ENV  old-value; 
     include   fastcgi_params; 
} 

例test.php的:

var_dump(getenv("TESTVAR_ENV")); 
var_dump(putenv("TESTVAR_ENV=new-value")); 
var_dump(getenv("TESTVAR_ENV")); 

test.php的的輸出:

string(12) "old-value" 
bool(true) 
string(12) "old-value" 

正如可以看到:

  1. 成功讀取現有值,
  2. putenv函數返回true,表示成功,
  3. 新值沒有實際設置,這是令人難以置信的混淆。

我誤解了putenv函數的用途是什麼? setenv手冊頁面上是否存在一些缺失的文檔?我如何使用putenv()來更新現有的環境變量?

+0

我從來沒見過這種行爲我自己。您是否嘗試先刪除舊值? 'putenv(「TESTVAR_ENV」)'應該清除該值,或者可以嘗試使用'$ _SERVER'來代替? – miken32

+1

實際上,只是用Nginx和PHP-FPM測試了這個,而不是CLI,我看到了同樣的情況。 – miken32

+0

您認爲這是PHP還是PHP-FPM的錯誤? – Greg

回答

2

這很有趣。經過調查,我發現undocumented parametergetenv()

調用putenv("TESTVAR_ENV=new-value")後跟getenv("TESTVAR_ENV", true)如預期的那樣返回new-value。但是,getenv("TESTVAR_ENV", true)在未明確設置值的情況下調用時會返回false。

從它看來,如果local_only設置爲false(默認值),使用sapi_getenv,而與local_only設置爲true,本地getenv使用值是牽強的source閱讀。

此外,如果sapi_getenv沒有返回值,則getenv被稱爲回退。這意味着如果您根本沒有在nginx/Apache配置中設置TESTVAR_ENV,則putenv/getenv按預期工作。

因此,要回顧:從SAPI的(PHP-FPM)

  • getenv(name)搜索內部環境表,並回退給OS的環境變量,如果沒有設置。
  • getenv(name, true)僅從OS環境進行搜索,不一定(取決於SAPI)包含Web服務器配置中註冊的變量。
  • putenv()始終只更新操作系統的環境。

我用下面來測試這一點:

header("Content-Type: text/plain"); 

dump_env(); 
echo 'getenv("TESTVAR_ENV") => ' . 
    var_export(getenv("TESTVAR_ENV"), true) . "\n"; 
echo 'getenv("TESTVAR_ENV", true) => ' . 
    var_export(getenv("TESTVAR_ENV", true), true) . "\n"; 
echo "-----------\n"; 
echo 'putenv("TESTVAR_ENV=new-value") => ' . 
    var_export(putenv("TESTVAR_ENV=new-value"), true) . "\n"; 
dump_env(); 
echo 'getenv("TESTVAR_ENV") => ' . 
    var_export(getenv("TESTVAR_ENV"), true) . "\n"; 
echo 'getenv("TESTVAR_ENV", true) => ' . 
    var_export(getenv("TESTVAR_ENV", true), true) . "\n"; 

function dump_env() { 
    echo "--- env ---\n" . `env` . "-----------\n"; 
} 
+0

感謝您對此的意見。我已經更新了php.net上的文檔以反映這種行爲,但我仍然認爲功能可能會有所改進。 – Greg