Proc_open返回标准输出,从不返回stderr

时间:2018-09-03 12:02:51

标签: php

我正在构建一个API,在该类的某个点上,我创建了一个cmd函数,该函数执行以下操作:

public function cmd($cmd)
{
    $return_array   = [];
    $descriptorspec = array(
        0 => array("pipe", "r"), // stdin
        1 => array("pipe", "w"), // stdout
        2 => array("pipe", "w"), // stderr
    );
    //Comando, array con gli std[] e pipes
    $process = proc_open($cmd, $descriptorspec, $pipes);

    if (is_resource($process)) {
        //Esegue $cmd: stdin
        fputs($pipes[0], "");
        fclose($pipes[0]);

        //Se in risposta c'è stdout
        while ($f = fgets($pipes[1])) {
            $arr = array_push($return_array, $f);
        }

        fclose($pipes[1]);
        $this->good($return_array);

        //Se in risposta c'è stderr
        while ($f = fgets($pipes[2])) {
            $arr = array_push($return_array, $f);
        }

        fclose($pipes[2]);
        $this->bad($f);

        //Chiusura del process
        proc_close($process);
    }
}

[您可以跳过意大利语注释]

然后我有good()bad()函数,分别在stdoutstderr上调用。 (惊人的函数名称)

运行此命令(查找不存在的目录)时,API返回$this->good()

$this->cmd("if [ -d '/tmp/idontexist' ]; then du -s /tmp/idontexist | cut -d '\t' -f1; else echo 'directory not found' 1>&2; fi");

然后我了解到stdout实际上总是存在的,所以我试图把心思集中在如何实现stderr进入$this->bad()的过程中,以使stdout进入$this->good()

1 个答案:

答案 0 :(得分:1)

不确定是否是问题所在,但是在处理stderr时,您有...

//Se in risposta c'è stderr
while ($f = fgets($pipes[2])) {
    $arr = array_push($return_array, $f);
}

fclose($pipes[2]);
$this->bad($f);

因此,这是将stderr的输出添加到$return_array,然后在$f中传递最后一行文本(最后将只包含false的文件)...

$this->bad($f);

您可能要对stdout处理使用其他数组,因此请尝试...

//Se in risposta c'è stderr
$errors = [];
while ($f2 = fgets($pipes[2])) {
    array_push($errors, $f2);
}

fclose($pipes[2]);
$this->bad($errors);

修改

此外,您应该检查返回的数组内容并仅在bad()good()实际包含某些内容时执行它们:

fclose($pipes[1]);
if(count($return_array)){
    $this->good($return_array);
}

//Se in risposta c'è stderr
while ($f2 = fgets($pipes[2])) {
    $arr = array_push($errors, $f2);
}

fclose($pipes[2]);
if(count($errors)){
    $this->bad($errors);
}