當前位置: 首頁> 最新文章列表> 怎麼用proc_terminate配合stream_get_contents獲取子進程輸出?

怎麼用proc_terminate配合stream_get_contents獲取子進程輸出?

gitbox 2025-06-09

1. 什麼是proc_open

proc_open是PHP中的一個函數,允許我們啟動一個進程,並與該進程進行交互。它能讓你讀取子進程的輸出、寫入輸入,甚至獲取進程的錯誤輸出。與execshell_exec不同, proc_open能夠提供更強大的控制功能。

2. 如何使用proc_open來啟動子進程?

首先,我們需要使用proc_open來啟動一個子進程。 proc_open的第一個參數是命令字符串,第二個參數是管道配置,第三個參數是用來接收子進程輸出和錯誤的數組。

以下是一個簡單的例子:

 $cmd = "ls -l";  // 你可以替換成任何命令
$descriptorspec = [
    1 => ['pipe', 'w'],  // 標準輸出
    2 => ['pipe', 'w'],  // 標準錯誤
];

$process = proc_open($cmd, $descriptorspec, $pipes);

if (is_resource($process)) {
    // 讀取子進程的輸出
    $output = stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    // 读取標準錯誤(如果有)
    $error_output = stream_get_contents($pipes[2]);
    fclose($pipes[2]);

    // 關閉進程
    $exit_code = proc_close($process);

    echo "Output:\n" . $output . "\n";
    if ($error_output) {
        echo "Error Output:\n" . $error_output . "\n";
    }
    echo "Exit Code: " . $exit_code . "\n";
}

在這個例子中,我們啟動了ls -l命令,並使用stream_get_contents讀取其標準輸出和標準錯誤。 proc_open允許我們在進程執行期間與其進行交互,而stream_get_contents則用來獲取輸出流中的內容。


3. 使用proc_terminate終止子進程

在某些情況下,可能需要強制結束子進程,尤其是在子進程運行時間過長或卡住時。 proc_terminate函數可以用來終止正在運行的子進程。

以下是使用proc_terminate終止進程的示例:

 $cmd = "sleep 10";  // 讓進程睡眠10秒,以模擬一個長時間運行的進程
$descriptorspec = [
    1 => ['pipe', 'w'],
    2 => ['pipe', 'w'],
];

$process = proc_open($cmd, $descriptorspec, $pipes);

if (is_resource($process)) {
    // 等待幾秒鐘後終止子進程
    sleep(3);
    proc_terminate($process);  // 強制終止進程

    // 讀取輸出和錯誤
    $output = stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    $error_output = stream_get_contents($pipes[2]);
    fclose($pipes[2]);

    echo "Output after termination:\n" . $output . "\n";
    if ($error_output) {
        echo "Error Output:\n" . $error_output . "\n";
    }

    // 獲取進程退出代碼
    $exit_code = proc_close($process);
    echo "Exit Code: " . $exit_code . "\n";
}

在這個例子中,我們使用sleep 10模擬了一個長時間運行的進程,然後在3秒後使用proc_terminate終止了該進程。注意,終止進程後,我們仍然可以獲取到子進程的輸出和錯誤信息。


4. 綜合示例:如何同時獲取子進程輸出和錯誤,並控制進程?

綜合之前的內容,以下是一個完整的示例,展示瞭如何啟動一個進程、獲取輸出、錯誤輸出,並在必要時終止進程。

 $cmd = "ping -c 4 google.com";  // 用於測試的命令,ping Google
$descriptorspec = [
    1 => ['pipe', 'w'],  // 標準輸出
    2 => ['pipe', 'w'],  // 標準錯誤
];

$process = proc_open($cmd, $descriptorspec, $pipes);

if (is_resource($process)) {
    // 讀取進程的輸出
    $output = stream_get_contents($pipes[1]);
    fclose($pipes[1]);

    // 读取標準錯誤输出
    $error_output = stream_get_contents($pipes[2]);
    fclose($pipes[2]);

    // 關閉進程并获取退出代码
    $exit_code = proc_close($process);

    echo "Output:\n" . $output . "\n";
    if ($error_output) {
        echo "Error Output:\n" . $error_output . "\n";
    }

    echo "Exit Code: " . $exit_code . "\n";
}

在這個示例中,我們使用ping命令來測試一個網絡連接,並通過proc_open啟動進程,讀取輸出和錯誤信息。