【问题标题】:Executing program in php - display and return output在 php 中执行程序 - 显示并返回输出
【发布时间】:2012-02-27 16:02:57
【问题描述】:

在 php 中有几种方法可以执行 shell 命令:

  • 系统()
  • passthru()
  • shell_exec()
  • exec()

前两个显示输出但不返回。 最后两个返回输出但不显示。

我想运行需要大量时间的 shell 命令,但它会显示一些输出,所以我知道它不会挂起。但是最后我想在 php.ini 中处理这个输出。如果我选择前两个中的一个,我将不会得到输出,所以我将无法在 php.ini 中处理它。如果我运行最后两个之一,我将能够处理输出,但是我的程序将挂起很长时间而不输出任何内容。

有没有办法运行一个shell命令,它会立即显示输出并返回它?

【问题讨论】:

  • system() 调用的第二个参数没有帮助吗?
  • 第二个参数是执行命令的返回状态,例如如果一切正常,则为 0,如果有错误,则为 1。我应该提到我也需要这个 - shell_exec() 是不支持的。
  • 我认为没有任何 PHP 命令会在执行完成之前执行 shell 代码并将输出打印到屏幕上。

标签: php shell


【解决方案1】:

也许这个你会感兴趣? proc_open() - http://www.php.net/manual/en/function.proc-open.php

这里有一个方便的 sn-p 可能对你有用(它是从我给你链接的网站上的 cmets 复制的):

<?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);
}
?>

【讨论】:

  • 谢谢!我无法推断出如何获得返回状态码:)
【解决方案2】:

也许您可以使用popen(),它执行程序并通过文件句柄读取其输出,如下所示:

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

【讨论】:

  • 谢谢!这会起作用,但是我忘了提到我还需要返回已执行命令的状态,所以可能 proc_open (类似的)将允许我这样做 - 无论如何谢谢!
猜你喜欢
  • 2015-06-20
  • 1970-01-01
  • 1970-01-01
  • 2011-05-23
  • 1970-01-01
  • 1970-01-01
  • 2011-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多