2012-02-27 63 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