關於 swbrown 的評論...如果您不希望顯示資料,則需要使用輸出緩衝區。
例如:
ob_start();
passthru("<i>command</i>");
$var = ob_get_contents();
ob_end_clean(); //使用這個而不是 ob_flush()
這會取得指令的所有輸出,並在不將任何資料傳送到標準輸出 (stdout) 的情況下結束。
(PHP 4, PHP 5, PHP 7, PHP 8)
passthru — 執行外部程式並顯示原始輸出
passthru() 函式與 exec() 函式類似,它會執行 command
指令。當 Unix 指令的輸出是需要直接傳回瀏覽器的二進位資料時,應該使用這個函式來取代 exec() 或 system()。一個常見的用途是執行類似 pbmplus 工具程式之類的程式,可以直接輸出影像串流。透過將 Content-type 設定為 image/gif
,然後呼叫 pbmplus 程式來輸出 gif,您可以建立直接輸出影像的 PHP 腳本。
command
將被執行的指令。
result_code
如果提供了 result_code
參數,Unix 指令的返回狀態將會被放置在此。
版本 | 說明 |
---|---|
8.0.0 | 如果 command 為空或包含空位元組,passthru() 現在會拋出 ValueError 例外。先前它會發出 E_WARNING 錯誤並返回 false 。 |
當允許使用者提供的資料傳遞給此函式時,請使用 escapeshellarg() 或 escapeshellcmd() 來確保使用者無法欺騙系統執行任意指令。
注意:
如果使用此函式啟動程式,為了讓它在背景繼續執行,程式的輸出必須重新導向到檔案或其他輸出串流。否則將導致 PHP 停滯,直到程式執行結束。
關於 swbrown 的評論...如果您不希望顯示資料,則需要使用輸出緩衝區。
例如:
ob_start();
passthru("<i>command</i>");
$var = ob_get_contents();
ob_end_clean(); //使用這個而不是 ob_flush()
這會取得指令的所有輸出,並在不將任何資料傳送到標準輸出 (stdout) 的情況下結束。
給 Paul Giblock 的說明:該指令*會*透過 shell 執行。
您可以在任何 Linux 系統上使用以下程式碼驗證:
<?php
passthru ('echo $PATH');
?>
您會得到 PATH 環境變數的內容,而不是字串 $PATH。
如果您在使用 passthru("docker-compose ...bash") 時遇到失去互動式 shell 大小資訊的問題,請嘗試改用 proc_open,因為基於某些原因,當我使用 proc_open 時,docker-compose bash 會知道外部終端機的大小,但當我使用 passthru 時,它會失去該資訊。
例如,我將
<?php
passthru("docker-compose -f docker-compose.yml bash",$ret);
?>
取代為
<?php
$empty1=array();
$empty2=array();
$proc=proc_open("docker-compose -f docker-compose.yml bash",$empty1,$empty2 );
$ret = proc_close($proc);
?>
然後 docker-compose bash 就突然知道我的終端機大小了 :)
如果您使用類似以下程式碼的 passthru() 來下載檔案(用於動態產生的內容或 Web 伺服器根目錄之外的內容):
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"myfile.zip\"");
header("Content-Length: 11111");
passthru("cat myfile.zip",$err);
而且您的下載進行順利,但後續的下載/連結點擊卻出錯,標頭和二進位資料散落在整個網站上,請嘗試在 passthru 之後加上
exit();
這會在下載完成後結束指令碼,並且不會干擾任何後續動作。
我試圖實作一個允許使用參數執行任意 CLI 指令的系統,但我一直遇到指令中使用者提示的問題,因為它們會導致執行掛起。解決方案很簡單:只需使用 passthru(),因為它會輸出所有內容並正確處理使用者提示。
使用 passthru 時,請記得使用完整路徑(例如 '/usr/local/bin/foo' 而不是 'foo'),否則會收到 exit code 127(找不到指令)。
PHP 的程式執行指令在處理 STDERR 時表現很差,而且 proc_open() 指令在 Windows 的非阻塞模式下運作也不太穩定。
這個指令雖然有用,但情況也一樣。要建立一個可以查看/擷取 STDOUT 和 STDERR 輸出的機制,請將指令透過管道傳送到 'tee' 指令(Windows 也找得到),並將整個過程包在輸出緩衝區中。
Dustin Oprea
Zak Estrada
2004年12月14日 上午11:21
使用 passthru 時,請記得使用完整路徑(例如 '/usr/local/bin/foo' 而不是 'foo'),否則會收到 exit code 127(找不到指令)。
請記住,如果您的檔案沒有執行權限,也會出現這個錯誤。
如果您已經對 Apache 和 PHP 進行了 chroot,您也需要將 /bin/sh 放入 chroot 環境中。否則,exec() 或 passthru() 將無法正常運作,並會產生錯誤代碼 127,找不到檔案。
我寫了一個函式,可以從 Internet Explorer(從
登錄檔)取得 Proxy 伺服器的值。它已在 Windows XP Pro 中測試過
(我的英文不好,請見諒)
<?php
function getProxyFromIE()
{
exec("reg query \"HKEY_CURRENT_USER\Software\Microsoft".
"\Windows\CurrentVersion\Internet Settings\" /v ProxyEnable",
$proxyenable,$proxyenable_status);
exec("reg query \"HKEY_CURRENT_USER\Software\Microsoft".
"\Windows\CurrentVersion\Internet Settings\" /v ProxyServer",
$proxyserver);
if($proxyenable_status!=0)
return false; #無法存取登錄檔!非常糟糕...
else
{
$enabled=substr($proxyenable[4],-1,1);
if($enabled==0)
return false;
else
{
$proxy=ereg_replace("^[ \t]{1,10}ProxyServer\tREG_SZ[ \t]{1,20}","",
$proxyserver[4]);
if(ereg("[\=\;]",$proxy))
{
$proxy=explode(";",$proxy);
foreach($proxy as $i => $v)
{
if(ereg("http",$v))
{
$proxy=str_replace("http=","",$v);
break;
}
}
if(@!ereg("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\:".
"[0-9]{1,5}$",$proxy))
return false;
else
return $proxy;
}
else
return $proxy;
}
}
}
?>
注意,如果在 Internet
Explorer 中停用了代理伺服器,則此函式會傳回 FALSE。此函式僅傳回 HTTP 代理伺服器。
用法
<?php
$proxy=getProxyFromIE();
if(!$proxy)
echo "無法取得代理伺服器!";
else
echo $proxy;
?>
我不確定其他人是否覺得這個有用,但當我嘗試在 Suse9.3 上使用 passthru() 命令時,以下命令卻沒有成功
$command = 'gdal_translate blahahahaha';
passthru($command);
它只在我輸入以下內容後才起作用
$command = '/usr/bin/local/gdal_translate blalalala';
passthru($command);
無論您做什麼,即使使用 ob_implicit_flush(),passthru() 似乎也絕對會緩衝輸出。解決方案似乎是改用 popen()。
文件中並未提及 passthru() 只會顯示標準輸出,而不會顯示標準錯誤輸出。
如果您正在執行腳本,您可以透過執行以下指令將標準錯誤輸出導向至標準輸出:
exec 2>&1
例如,以下腳本實際上會使用 passthru() 函式印出一些內容...
#!/bin/sh
exec 2>&1
ulimit -t 60
cat nosuchfile.txt
認為有必要說明一下,在 Windows 的 DOS 環境下執行時 (在 NT 上測試),passthru() 似乎會抑制錯誤訊息。
要顯示包含錯誤的完整原始輸出,請使用 system()。