2024 年 PHP Conference Japan

passthru

(PHP 4, PHP 5, PHP 7, PHP 8)

passthru執行外部程式並顯示原始輸出

說明

passthru(字串 $command, 整數 &$result_code = null): ?false

passthru() 函式與 exec() 函式類似,它會執行 command 指令。當 Unix 指令的輸出是需要直接傳回瀏覽器的二進位資料時,應該使用這個函式來取代 exec()system()。一個常見的用途是執行類似 pbmplus 工具程式之類的程式,可以直接輸出影像串流。透過將 Content-type 設定為 image/gif,然後呼叫 pbmplus 程式來輸出 gif,您可以建立直接輸出影像的 PHP 腳本。

參數

command

將被執行的指令。

result_code

如果提供了 result_code 參數,Unix 指令的返回狀態將會被放置在此。

返回值

成功時返回 null,失敗時返回 false

錯誤/例外

如果 passthru() 無法執行 command,將會發出 E_WARNING 錯誤。

如果 command 為空或包含空位元組,則會拋出 ValueError 例外。

更新日誌

版本 說明
8.0.0 如果 command 為空或包含空位元組,passthru() 現在會拋出 ValueError 例外。先前它會發出 E_WARNING 錯誤並返回 false

注意事項

警告

當允許使用者提供的資料傳遞給此函式時,請使用 escapeshellarg()escapeshellcmd() 來確保使用者無法欺騙系統執行任意指令。

注意:

如果使用此函式啟動程式,為了讓它在背景繼續執行,程式的輸出必須重新導向到檔案或其他輸出串流。否則將導致 PHP 停滯,直到程式執行結束。

參見

新增註解

使用者貢獻的筆記 15 則筆記

puppy at cyberpuppy dot org
19 年前
關於 swbrown 的評論...如果您不希望顯示資料,則需要使用輸出緩衝區。

例如:
ob_start();
passthru("<i>command</i>");
$var = ob_get_contents();
ob_end_clean(); //使用這個而不是 ob_flush()

這會取得指令的所有輸出,並在不將任何資料傳送到標準輸出 (stdout) 的情況下結束。
jo at durchholz dot org
17 年前
給 Paul Giblock 的說明:該指令*會*透過 shell 執行。
您可以在任何 Linux 系統上使用以下程式碼驗證:

<?php
passthru
('echo $PATH');
?>

您會得到 PATH 環境變數的內容,而不是字串 $PATH。
divinity76+spam at gmail dot com
2 年前
如果您在使用 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 就突然知道我的終端機大小了 :)
igor at bboy dot ru
19 年前
如果您使用類似以下程式碼的 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();

這會在下載完成後結束指令碼,並且不會干擾任何後續動作。
mail at dtrasbo dot dk
2 年前
要將指令的輸出擷取到字串中而不使用輸出緩衝區函式,請使用 shell_exec()
tox at novasonica dot com
5 年前
我試圖實作一個允許使用參數執行任意 CLI 指令的系統,但我一直遇到指令中使用者提示的問題,因為它們會導致執行掛起。解決方案很簡單:只需使用 passthru(),因為它會輸出所有內容並正確處理使用者提示。
Zak Estrada
19 年前
使用 passthru 時,請記得使用完整路徑(例如 '/usr/local/bin/foo' 而不是 'foo'),否則會收到 exit code 127(找不到指令)。
myselfasunder at gmail dot com dot dfvuks
14 年前
PHP 的程式執行指令在處理 STDERR 時表現很差,而且 proc_open() 指令在 Windows 的非阻塞模式下運作也不太穩定。

這個指令雖然有用,但情況也一樣。要建立一個可以查看/擷取 STDOUT 和 STDERR 輸出的機制,請將指令透過管道傳送到 'tee' 指令(Windows 也找得到),並將整個過程包在輸出緩衝區中。

Dustin Oprea
sarel dot w at envent dot co dot za
19 年前
Zak Estrada
2004年12月14日 上午11:21
使用 passthru 時,請記得使用完整路徑(例如 '/usr/local/bin/foo' 而不是 'foo'),否則會收到 exit code 127(找不到指令)。

請記住,如果您的檔案沒有執行權限,也會出現這個錯誤。
Chroot
16 年前
如果您已經對 Apache 和 PHP 進行了 chroot,您也需要將 /bin/sh 放入 chroot 環境中。否則,exec() 或 passthru() 將無法正常運作,並會產生錯誤代碼 127,找不到檔案。
nuker at list dot ru
18 年前
我寫了一個函式,可以從 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;
?>
Stuart Eve
18 年前
我不確定其他人是否覺得這個有用,但當我嘗試在 Suse9.3 上使用 passthru() 命令時,以下命令卻沒有成功

$command = 'gdal_translate blahahahaha';

passthru($command);

它只在我輸入以下內容後才起作用

$command = '/usr/bin/local/gdal_translate blalalala';

passthru($command);
swbrown at ucsd dot edu
21 年前
無論您做什麼,即使使用 ob_implicit_flush(),passthru() 似乎也絕對會緩衝輸出。解決方案似乎是改用 popen()。
kpierre at fit dot edu
22 年前
文件中並未提及 passthru() 只會顯示標準輸出,而不會顯示標準錯誤輸出。

如果您正在執行腳本,您可以透過執行以下指令將標準錯誤輸出導向至標準輸出:

exec 2>&1

例如,以下腳本實際上會使用 passthru() 函式印出一些內容...

#!/bin/sh
exec 2>&1
ulimit -t 60
cat nosuchfile.txt
stuartc1 at NOSPAM dot hotmail dot com
19 年前
認為有必要說明一下,在 Windows 的 DOS 環境下執行時 (在 NT 上測試),passthru() 似乎會抑制錯誤訊息。

要顯示包含錯誤的完整原始輸出,請使用 system()。
To Top