首頁  >  文章  >  後端開發  >  重定向 - php執行shell腳本,得到標準輸出和錯誤輸出

重定向 - php執行shell腳本,得到標準輸出和錯誤輸出

WBOY
WBOY原創
2016-09-08 08:43:571974瀏覽

1.問題

在php程式碼中需要執行一個shell腳本,希望分別得到它的標準輸出(stdout)錯誤輸出(stderr)。用shell的重定向把標準輸出和錯誤輸出放到文件中再用php讀取文件,可行,但輸出文件的內容傳回php後就不再需要,有沒有辦法把shell的輸出重定向到變數?

要執行腳本的功能,無法用php本身完成(執行R語言的腳本),並且需要把常規輸出和錯誤輸出都回饋。

2.已有嘗試

shell裡面的重定向可以把標準輸出和錯誤輸出分別放到檔案中,但產生臨時檔案。

<code class="bash">my_cmd 1>out.txt 2>err.txt</code>

php再讀取out.txterr.txt檔案內容進行回傳。

這樣做的缺點:產生了中間文件。如果shell指令my_cmd執行的時間比較長(可能要幾分鐘),那麼同一用戶如果短時間內多次發起http請求使得php執行my_cmd,則需要每次out.txterr. txt的名字都不同,以免寫入衝突。這就產生了很多不必要的中間文件。即使及時刪除它們,對於I/O還是有開銷,希望能避免。

php的exec()函數:

<code>string exec ( string $command [, array &$output [, int &$return_var ]] )</code>

裡面的參數$output看起來只能得到「執行腳本時螢幕輸出」的內容,是stdout或stdout和stderr的混合,不能分開取得。

回覆內容:

1.問題

在php程式碼中需要執行一個shell腳本,希望分別得到它的標準輸出(stdout)錯誤輸出(stderr)。用shell的重定向把標準輸出和錯誤輸出放到文件中再用php讀取文件,可行,但輸出文件的內容傳回php後就不再需要,有沒有辦法把shell的輸出重定向到變數?

要執行腳本的功能,無法用php本身完成(執行R語言的腳本),並且需要把常規輸出和錯誤輸出都回饋。

2.已有嘗試

shell裡面的重定向可以把標準輸出和錯誤輸出分別放到檔案中,但產生臨時檔案。

<code class="bash">my_cmd 1>out.txt 2>err.txt</code>

php再讀取out.txterr.txt檔案內容進行回傳。

這樣做的缺點:產生了中間文件。如果shell指令my_cmd執行的時間比較長(可能要幾分鐘),那麼同一用戶如果短時間內多次發起http請求使得php執行my_cmd,則需要每次out.txterr. txt的名字都不同,以免寫入衝突。這就產生了很多不必要的中間文件。即使及時刪除它們,對於I/O還是有開銷,希望能避免。

php的exec()函數:

<code>string exec ( string $command [, array &$output [, int &$return_var ]] )</code>

裡面的參數$output看起來只能得到「運行腳本時螢幕輸出」的內容,是stdout或stdout和stderr的混合,不能分開獲得。

找到答案了,自問自答一次。
使用proc_open()函數,它能執行​​一段shell腳本,並且把stdout和stderr分別儲存,也支援設定stdin:

<code>resource proc_open ( string $cmd , array $descriptorspec , array &$pipes [, string $cwd [, array $env [, array $other_options ]]] )</code>

參考代碼:

<code class="php">$descriptorspec = array(
        0 => array("pipe", "r"),    // stdin
        1 => array("pipe", "w"),    // stdout
        2 => array("pipe", "w")     // stderr
    );

    $cmd = 'Rscript hello.r';  // 替换为你要执行的shell脚本
    $proc = proc_open($cmd, $descriptorspec, $pipes, null, null);

    // $proc为false,表明命令执行失败
    if ($proc == false) {
        // do sth with HTTP response
    } else {
        $stdout = stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        $stderr = stream_get_contents($pipes[2]);
        fclose($pipes[2]);
        $status = proc_close($proc);  // 释放proc
    }

    $data = array(
        'code' => 0,
        'msg' => array(
            'stdout' => $stdout,
            'stderr' => $stderr,
            'retval' => $status
        )
    );
    
    // do sth with $data to HTTP response</code>
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn