(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
proc_open — 執行一個(gè)命令,并且打開(kāi)用來(lái)輸入/輸出的文件指針。
$cmd
,$descriptorspec
,&$pipes
,$cwd
= null
,$env
= null
,$other_options
= null
類(lèi)似 popen() 函數, 但是 proc_open() 提供了更加強大的控制程序執行的能力。
cmd
以 string 形式執行的命令行。特殊字符必須經(jīng)過(guò)轉義,并且使用正確的引號。
注意: 在 Windows 上, 除非在
other_options
中 把bypass_shell
設置為true
,否則cmd
會(huì )被傳遞給 cmd.exe (實(shí)際上是%ComSpec%
) 其中的/c
標志是 未加引號的 字符串 (也就是和 proc_open() 一樣)。 這可能會(huì )導致 cmd.exe 刪除cmd
中的引號 (詳見(jiàn) cmd.exe 文檔), 從而導致意外的,甚至是潛在的危險行為,因為 cmd.exe 錯誤消息可能包含 (部分) 傳遞的cmd
(見(jiàn)下面的例子)。
從 PHP 7.4.0 開(kāi)始,cmd
參數可以使用 array 類(lèi)型傳遞。
在這種情況下,進(jìn)程將直接打開(kāi)(不通過(guò) shell )。
而 PHP 會(huì )處理任何必要的參數轉義。
注意:
在 Windows 上, array 元素的參數轉義假定 執行命令的命令行解析與 VC 運行時(shí)進(jìn)行的命令行參數解析兼容。
descriptorspec
一個(gè)索引數組。 數組的鍵表示描述符,數組元素值表示 PHP 如何將這些描述符傳送至子進(jìn)程。 0 表示標準輸入(stdin),1 表示標準輸出(stdout),2 表示標準錯誤(stderr)。
數組中的元素可以是:
pipe
(第二個(gè)元素可以是: r
向進(jìn)程傳送該管道的讀取端,w
向進(jìn)程傳送該管道的寫(xiě)入端),
以及 file
(第二個(gè)元素為文件名)。
STDIN
)。
文件描述符的值不限于 0,1 和 2,你可以使用任何有效的文件描述符 并將其傳送至子進(jìn)程。 這使得你的腳本可以和其他腳本交互操作。 例如,可以通過(guò)指定文件描述符將密碼以更加安全的方式 傳送至諸如 PGP,GPG 和 openssl 程序, 同時(shí)也可以很方便的獲取這些程序的狀態(tài)信息。
pipes
將被置為索引數組, 其中的元素是被執行程序創(chuàng )建的管道對應到 PHP 這一端的文件指針。
cwd
要執行命令的初始工作目錄。
必須是 絕對 路徑,
設置此參數為 null
表示使用默認值(當前 PHP 進(jìn)程的工作目錄)。
env
要執行的命令所使用的環(huán)境變量。
設置此參數為 null
表示使用和當前 PHP 進(jìn)程相同的環(huán)境變量。
other_options
你還可以指定一些附加選項。 目前支持的選項包括:
suppress_errors
(僅用于 Windows 平臺):
設置為 true
表示抑制本函數產(chǎn)生的錯誤。
bypass_shell
(僅用于 Windows 平臺):
設置為 true
表示繞過(guò) cmd.exe
shell。
blocking_pipes
(僅用于 Windows 平臺):
設置為 true
表示強制堵塞管道。
create_process_group
(僅用于 Windows 平臺):
設置為 true
表示允許子進(jìn)程處理 CTRL
事件。
create_new_console
(僅用于 Windows 平臺):
表示新進(jìn)程有一個(gè)新的控制臺,用于代替父進(jìn)程的控制臺。
返回表示進(jìn)程的資源類(lèi)型,
當使用完畢之后,請調用 proc_close() 函數來(lái)關(guān)閉此資源。
如果失敗,返回 false
。
版本 | 說(shuō)明 |
---|---|
7.4.4 |
為 other_options 參數增加 create_new_console 選項。
|
7.4.0 |
proc_open() 的 cmd 參數現在也允許數組類(lèi)型。
|
7.4.0 |
為 other_options 參數增加 create_process_group 選項。
|
示例 #1 proc_open() 例程
<?php
$descriptorspec = array(
0 => array("pipe", "r"), // 標準輸入,子進(jìn)程從此管道中讀取數據
1 => array("pipe", "w"), // 標準輸出,子進(jìn)程向此管道中寫(xiě)入數據
2 => array("file", "/tmp/error-output.txt", "a") // 標準錯誤,寫(xiě)入到一個(gè)文件
);
$cwd = '/tmp';
$env = array('some_option' => 'aeiou');
$process = proc_open('php', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
// $pipes 現在看起來(lái)是這樣的:
// 0 => 可以向子進(jìn)程標準輸入寫(xiě)入的句柄
// 1 => 可以從子進(jìn)程標準輸出讀取的句柄
// 錯誤輸出將被追加到文件 /tmp/error-output.txt
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// 切記:在調用 proc_close 之前關(guān)閉所有的管道以避免死鎖。
$return_value = proc_close($process);
echo "command returned $return_value\n";
}
?>
以上例程的輸出類(lèi)似于:
Array ( [some_option] => aeiou [PWD] => /tmp [SHLVL] => 1 [_] => /usr/local/bin/php ) command returned 0
示例 #2 proc_open() 在 Windows 上的怪異行為
雖然人們可能期望下面的程序能夠搜索文件 filename.txt 進(jìn)行文本搜索, 并打印結果,但它的行為相當不同。
<?php
$descriptorspec = [STDIN, STDOUT, STDOUT];
$cmd = '"findstr" "search" "filename.txt"';
$proc = proc_open($cmd, $descriptorspec, $pipes);
proc_close($proc);
?>
以上例程會(huì )輸出:
'findstr" "search" "filename.txt' is not recognized as an internal or external command, operable program or batch file.
要解決該行為,通常只需將 cmd
加上引號:
$cmd = '""findstr" "search" "filename.txt""';
注意:
Windows 兼容性:超過(guò) 2 的描述符也可以作為可繼承的句柄傳送到子進(jìn)程。 但是,由于 Windows 的架構并不將文件描述符和底層句柄進(jìn)行關(guān)聯(lián), 所以,子進(jìn)程無(wú)法訪(fǎng)問(wèn)這樣的句柄。 標準輸入,標準輸出和標注錯誤會(huì )按照預期工作。
注意:
如果你只需要單向的進(jìn)程管道, 使用 popen() 函數會(huì )更加簡(jiǎn)單。