2012-02-27 62 views
6

在php中有幾種方法來執行的外殼命令:執行程序在PHP - 顯示並返回輸出

  • 系統()
  • 通路()
  • 了shell_exec()
  • EXEC( )

前兩個顯示輸出但不返回。 最後兩個返回輸出,但不顯示它。

我想運行shell命令,它需要很多時間,但它顯示一些輸出,所以我知道它不會掛起。但最後我想在php中處理這個輸出。如果我選擇前兩個之一,我不會得到輸出,所以我將無法在PHP中處理它。如果我運行最後兩個中的一個,我將能夠處理輸出,但是我的程序將掛起很長時間而不輸出任何內容。

有沒有辦法運行一個shell命令,它將立即顯示輸出並返回它?

+0

請問第二個參數的系統()打電話沒有幫助? – KTastrophy 2012-02-27 16:10:19

+0

第二個參數是執行命令的返回狀態,例如如果一切正常,則爲0;如果有錯誤,則爲1。我應該提到我也需要這個 - shell_exec()是不支持的。 – 2012-02-27 16:12:41

+0

我不認爲有任何PHP命令會在執行完成前執行shell代碼並將輸出打印到屏幕上。 – Travesty3 2012-02-27 16:17:43

回答

2

也許這個人會感興趣嗎? proc_open() - http://www.php.net/manual/en/function.proc-open.php

這裏是一個方便的片斷這可能會爲你工作(它是從我給你鏈接到網站上的評論複製):

<?php 
/* 
* Execute and display the output in real time (stdout + stderr). 
* 
* Please note this snippet is prepended with an appropriate shebang for the 
* CLI. You can re-use only the function. 
* 
* Usage example: 
* chmod u+x proc_open.php 
* ./proc_open.php "ping -c 5 google.fr"; echo RetVal=$? 
*/ 
define(BUF_SIZ, 1024);  # max buffer size 
define(FD_WRITE, 0);  # stdin 
define(FD_READ, 1);  # stdout 
define(FD_ERR, 2);  # stderr 

/* 
* Wrapper for proc_*() functions. 
* The first parameter $cmd is the command line to execute. 
* Return the exit code of the process. 
*/ 
function proc_exec($cmd) 
{ 
    $descriptorspec = array(
     0 => array("pipe", "r"), 
     1 => array("pipe", "w"), 
     2 => array("pipe", "w") 
    ); 

    $ptr = proc_open($cmd, $descriptorspec, $pipes, NULL, $_ENV); 
    if (!is_resource($ptr)) 
     return false; 

    while (($buffer = fgets($pipes[FD_READ], BUF_SIZ)) != NULL 
      || ($errbuf = fgets($pipes[FD_ERR], BUF_SIZ)) != NULL) { 
     if (!isset($flag)) { 
      $pstatus = proc_get_status($ptr); 
      $first_exitcode = $pstatus["exitcode"]; 
      $flag = true; 
     } 
     if (strlen($buffer)) 
      echo $buffer; 
     if (strlen($errbuf)) 
      echo "ERR: " . $errbuf; 
    } 

    foreach ($pipes as $pipe) 
     fclose($pipe); 

    /* Get the expected *exit* code to return the value */ 
    $pstatus = proc_get_status($ptr); 
    if (!strlen($pstatus["exitcode"]) || $pstatus["running"]) { 
     /* we can trust the retval of proc_close() */ 
     if ($pstatus["running"]) 
      proc_terminate($ptr); 
     $ret = proc_close($ptr); 
    } else { 
     if ((($first_exitcode + 256) % 256) == 255 
       && (($pstatus["exitcode"] + 256) % 256) != 255) 
      $ret = $pstatus["exitcode"]; 
     elseif (!strlen($first_exitcode)) 
      $ret = $pstatus["exitcode"]; 
     elseif ((($first_exitcode + 256) % 256) != 255) 
      $ret = $first_exitcode; 
     else 
      $ret = 0; /* we "deduce" an EXIT_SUCCESS ;) */ 
     proc_close($ptr); 
    } 

    return ($ret + 256) % 256; 
} 

/* __init__ */ 
if (isset($argv) && count($argv) > 1 && !empty($argv[1])) { 
    if (($ret = proc_exec($argv[1])) === false) 
     die("Error: not enough FD or out of memory.\n"); 
    elseif ($ret == 127) 
     die("Command not found (returned by sh).\n"); 
    else 
     exit($ret); 
} 
?> 
+0

謝謝!我永遠不會推斷如何也得到返回狀態代碼:) – 2012-02-27 16:36:34

+0

沒問題,卡米爾。 :) – Pateman 2012-02-27 18:23:27

2

也許你可以使用popen(),執行程序,並通過一個文件句柄讀取它的輸出,就像這樣:

$handle = popen('/bin/ls', 'r'); 
while ($line = fread($handle, 100)){ 
    echo $line; 
} 
pclose($handle); 
+0

謝謝!這將工作,但我忘了提及我也需要返回執行命令的狀態,所以可能proc_open(這是類似的)將允許我這樣做 - 謝謝! – 2012-02-27 16:34:09

+0

不客氣。很高興你解決了它! – elias 2012-02-27 16:35:24