捕获/抑制 php exec 的所有输出,包括 stderr

Dan*_*elM 5 php stdout exec stderr

我想通过运行多个命令exec(),但我不想在屏幕上输出任何内容。然而,我确实想保留输出,以便我可以在脚本运行时控制详细程度。

这是我的课程:

<?php
class System
{
    public function exec($command, array &$output = [])
    {
        $returnVar = null;
        exec($command, $output, $returnVar);
        return $returnVar;
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,大多数应用程序都会将大量不相关的内容放入其中stderr,而我似乎无法阻止这些内容。例如,这是运行git clone它的输出:

Cloning into '/tmp/directory'...
remote: Counting objects: 649, done.
remote: Compressing objects: 100% (119/119), done.
remote: Total 649 (delta 64), reused 0 (delta 0), pack-reused 506
Receiving objects: 100% (649/649), 136.33 KiB | 0 bytes/s, done.
Resolving deltas: 100% (288/288), done.
Checking connectivity... done.
Run Code Online (Sandbox Code Playgroud)

我看到其他问题声称使用输出缓冲区可以工作,但它似乎不起作用

<?php
class System
{
    public function exec($command, array &$output = [])
    {
        $returnVar = null;
        ob_start();
        exec($command, $output, $returnVar);
        ob_end_clean();
        return $returnVar;
    }
}
Run Code Online (Sandbox Code Playgroud)

这仍然会产生相同的结果。我可以通过在命令中将 stderr 路由到 stdout 来解决该问题,但是,这不仅使我无法区分 stdout 和 stderr,而且该应用程序设计为在 Windows 和 Linux 中运行,因此现在这是一团糟。

<?php
class System
{
    public function exec($command, array &$output = [])
    {
        $returnVar = null;

        // Is Windows
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            exec($command, $output, $returnVar);
            return $returnVar;
        }

        // Is not windows
        exec("({$command}) 2>&1", $output, $returnVar);
        return $returnVar;
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法分别捕获和抑制 stderr 和 stdout?

更新/回答示例

根据评论中 @hexasoft 的建议,我更新了我的方法,如下所示:

<?php
class System
{
    public function exec($command, &$stdOutput = '', &$stdError = '')
    {
        $process = proc_open(
            $command,
            [
                0 => ['pipe', 'r'],
                1 => ['pipe', 'w'],
                2 => ['pipe', 'w'],
            ],
            $pipes
        );

        if (!is_resource($process)) {
            throw new \RuntimeException('Could not create a valid process');
        }

        // This will prevent to program from continuing until the processes is complete
        // Note: exitcode is created on the final loop here
        $status = proc_get_status($process);
        while($status['running']) {
            $status = proc_get_status($process);
        }

        $stdOutput = stream_get_contents($pipes[1]);
        $stdError  = stream_get_contents($pipes[2]);

        proc_close($process);

        return $status['exitcode'];
    }
}
Run Code Online (Sandbox Code Playgroud)

该技术提供了更高级的选项,包括异步进程。

小智 3

命令proc_exec()允许使用管道处理 exec-ed 命令的文件描述符。

\n\n

其功能是:proc_open ( string $cmd , array $descriptorspec , array &$pipes [\xe2\x80\xa6optional parameters] ) : resource

\n\n

你在 $cmd 中给你命令(如exec),并给出一个描述要“安装”该命令的文件描述符的数组。该数组按文件描述符编号(0 = stdin,1 = stdout \ xe2 \ x80 \ xa6)进行索引,并包含类型(文件,管道)和模式(r / w \ xe2 \ x80 \ xa6)以及文件的文件名类型。

\n\n

然后,您可以在 $pipes 中获取一个文件描述符数组,该数组可用于读取或写入(取决于请求的内容)。

\n\n

您不应忘记在使用后关闭这些描述符。

\n\n

请参阅 PHP 手册页(特别是示例): https: //php.net/manual/en/function.proc-open.php

\n\n

请注意,读/写与生成的命令相关,而不是与 PHP 脚本相关。

\n