= 4.3.0, PHP 5, PHP 7, PHP 8)proc_open — 執(zhí)行一個(gè)命令,并且打開(kāi)用來(lái)輸入/輸出的文件指針。 說(shuō)明proc_open( mixed $cmd, array $descriptorspec, array &$pi">

proc_open

(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)

proc_open 執(zhí)行一個(gè)命令,并且打開(kāi)用來(lái)輸入/輸出的文件指針。

說(shuō)明

proc_open(
    mixed $cmd,
    array $descriptorspec,
    array &$pipes,
    string $cwd = null,
    array $env = null,
    array $other_options = null
): resource

類似 popen() 函數(shù), 但是 proc_open() 提供了更加強(qiáng)大的控制程序執(zhí)行的能力。

參數(shù)

cmd

string 形式執(zhí)行的命令行。特殊字符必須經(jīng)過(guò)轉(zhuǎn)義,并且使用正確的引號(hào)。

注意: Windows 上, 除非在 other_options 中 把 bypass_shell 設(shè)置為 true ,否則 cmd 會(huì)被傳遞給 cmd.exe (實(shí)際上是 %ComSpec%) 其中的 /c 標(biāo)志是 未加引號(hào)的 字符串 (也就是和 proc_open() 一樣)。 這可能會(huì)導(dǎo)致 cmd.exe 刪除 cmd 中的引號(hào) (詳見(jiàn) cmd.exe 文檔), 從而導(dǎo)致意外的,甚至是潛在的危險(xiǎn)行為,因?yàn)? cmd.exe 錯(cuò)誤消息可能包含 (部分) 傳遞的 cmd (見(jiàn)下面的例子)。

從 PHP 7.4.0 開(kāi)始,cmd 參數(shù)可以使用 array 類型傳遞。 在這種情況下,進(jìn)程將直接打開(kāi)(不通過(guò) shell )。 而 PHP 會(huì)處理任何必要的參數(shù)轉(zhuǎn)義。

注意:

在 Windows 上, array 元素的參數(shù)轉(zhuǎn)義假定 執(zhí)行命令的命令行解析與 VC 運(yùn)行時(shí)進(jìn)行的命令行參數(shù)解析兼容。

descriptorspec

一個(gè)索引數(shù)組。 數(shù)組的鍵表示描述符,數(shù)組元素值表示 PHP 如何將這些描述符傳送至子進(jìn)程。 0 表示標(biāo)準(zhǔn)輸入(stdin),1 表示標(biāo)準(zhǔn)輸出(stdout),2 表示標(biāo)準(zhǔn)錯(cuò)誤(stderr)。

數(shù)組中的元素可以是:

  • 包含了要傳送至進(jìn)程的管道的描述信息的數(shù)組。 第一個(gè)元素為描述符類型, 第二個(gè)元素是針對(duì)該描述符的選項(xiàng)。 有效的類型有:pipe (第二個(gè)元素可以是: r 向進(jìn)程傳送該管道的讀取端,w 向進(jìn)程傳送該管道的寫入端), 以及 file(第二個(gè)元素為文件名)。
  • 表達(dá)一個(gè)真實(shí)文件描述符的流資源類型 (例如:已打開(kāi)的文件,一個(gè) socket 端口,STDIN)。

文件描述符的值不限于 0,1 和 2,你可以使用任何有效的文件描述符 并將其傳送至子進(jìn)程。 這使得你的腳本可以和其他腳本交互操作。 例如,可以通過(guò)指定文件描述符將密碼以更加安全的方式 傳送至諸如 PGP,GPG 和 openssl 程序, 同時(shí)也可以很方便的獲取這些程序的狀態(tài)信息。

pipes

將被置為索引數(shù)組, 其中的元素是被執(zhí)行程序創(chuàng)建的管道對(duì)應(yīng)到 PHP 這一端的文件指針。

cwd

要執(zhí)行命令的初始工作目錄。 必須是 絕對(duì) 路徑, 設(shè)置此參數(shù)為 null 表示使用默認(rèn)值(當(dāng)前 PHP 進(jìn)程的工作目錄)。

env

要執(zhí)行的命令所使用的環(huán)境變量。 設(shè)置此參數(shù)為 null 表示使用和當(dāng)前 PHP 進(jìn)程相同的環(huán)境變量。

other_options

你還可以指定一些附加選項(xiàng)。 目前支持的選項(xiàng)包括:

  • suppress_errors (僅用于 Windows 平臺(tái)): 設(shè)置為 true 表示抑制本函數(shù)產(chǎn)生的錯(cuò)誤。
  • bypass_shell (僅用于 Windows 平臺(tái)): 設(shè)置為 true 表示繞過(guò) cmd.exe shell。
  • blocking_pipes (僅用于 Windows 平臺(tái)): 設(shè)置為 true 表示強(qiáng)制堵塞管道。
  • create_process_group (僅用于 Windows 平臺(tái)): 設(shè)置為 true 表示允許子進(jìn)程處理 CTRL 事件。
  • create_new_console (僅用于 Windows 平臺(tái)): 表示新進(jìn)程有一個(gè)新的控制臺(tái),用于代替父進(jìn)程的控制臺(tái)。

返回值

返回表示進(jìn)程的資源類型, 當(dāng)使用完畢之后,請(qǐng)調(diào)用 proc_close() 函數(shù)來(lái)關(guān)閉此資源。 如果失敗,返回 false

更新日志

版本 說(shuō)明
7.4.4 other_options 參數(shù)增加 create_new_console 選項(xiàng)。
7.4.0 proc_open()cmd 參數(shù)現(xiàn)在也允許數(shù)組類型。
7.4.0 other_options 參數(shù)增加 create_process_group 選項(xiàng)。

范例

示例 #1 proc_open() 例程

<?php
$descriptorspec 
= array(
   
=> array("pipe""r"),  // 標(biāo)準(zhǔn)輸入,子進(jìn)程從此管道中讀取數(shù)據(jù)
   
=> array("pipe""w"),  // 標(biāo)準(zhǔn)輸出,子進(jìn)程向此管道中寫入數(shù)據(jù)
   
=> array("file""/tmp/error-output.txt""a"// 標(biāo)準(zhǔn)錯(cuò)誤,寫入到一個(gè)文件
);

$cwd '/tmp';
$env = array('some_option' => 'aeiou');

$process proc_open('php'$descriptorspec$pipes$cwd$env);

if (
is_resource($process)) {
    
// $pipes 現(xiàn)在看起來(lái)是這樣的:
    // 0 => 可以向子進(jìn)程標(biāo)準(zhǔn)輸入寫入的句柄
    // 1 => 可以從子進(jìn)程標(biāo)準(zhǔn)輸出讀取的句柄
    // 錯(cuò)誤輸出將被追加到文件 /tmp/error-output.txt

    
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
    
fclose($pipes[0]);

    echo 
stream_get_contents($pipes[1]);
    
fclose($pipes[1]);
    

    
// 切記:在調(diào)用 proc_close 之前關(guān)閉所有的管道以避免死鎖。
    
$return_value proc_close($process);

    echo 
"command returned $return_value\n";
}
?>

以上例程的輸出類似于:

Array
(
    [some_option] => aeiou
    [PWD] => /tmp
    [SHLVL] => 1
    [_] => /usr/local/bin/php
)
command returned 0

示例 #2 proc_open() 在 Windows 上的怪異行為

雖然人們可能期望下面的程序能夠搜索文件 filename.txt 進(jìn)行文本搜索, 并打印結(jié)果,但它的行為相當(dāng)不同。

<?php
$descriptorspec 
= [STDINSTDOUTSTDOUT];
$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 加上引號(hào):

$cmd = '""findstr" "search" "filename.txt""';

注釋

注意:

Windows 兼容性:超過(guò) 2 的描述符也可以作為可繼承的句柄傳送到子進(jìn)程。 但是,由于 Windows 的架構(gòu)并不將文件描述符和底層句柄進(jìn)行關(guān)聯(lián), 所以,子進(jìn)程無(wú)法訪問(wèn)這樣的句柄。 標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出和標(biāo)注錯(cuò)誤會(huì)按照預(yù)期工作。

注意:

如果你只需要單向的進(jìn)程管道, 使用 popen() 函數(shù)會(huì)更加簡(jiǎn)單。

參見(jiàn)

  • popen() - 打開(kāi)進(jìn)程文件指針
  • exec() - 執(zhí)行一個(gè)外部程序
  • system() - 執(zhí)行外部程序,并且顯示輸出
  • passthru() - 執(zhí)行外部程序并且顯示原始輸出
  • stream_select() - Runs the equivalent of the select() system call on the given arrays of streams with a timeout specified by seconds and microseconds
  • The 執(zhí)行運(yùn)算符