FEOF 生成无限循环

feof generates infinite loop

提问人:Alexandr Suleymanov 提问时间:4/23/2015 最后编辑:Alexandr Suleymanov 更新时间:2/3/2020 访问量:943

问:

所以我做了一件简单的事情,首先我通过ssh2_exec执行命令(成功验证后),然后在变量中读取答案。我的代码如下(未进行身份验证)

try {
        $stdout_stream = ssh2_exec($this->connection, $_cmd);
        $stderr_stream = ssh2_fetch_stream($stdout_stream, \SSH2_STREAM_STDERR);
    } catch (Exception $e) {
        $std_output = $e->getMessage();
        return false;
    }

    $output = "";

    while (!feof($stdout_stream)) {
        $output .= fgets($stdout_stream, 4096);
    }

    while (!feof($stderr_stream)) {
        $output .= fgets($stderr_stream, 4096);
    }

    fclose($stdout_stream);
    fclose($stderr_stream);     

    return $output;

例如,我尝试执行这样的cmd:

sudo service httpd stop && sudo service httpd start

因此,当命令执行良好时,一切都很好,响应是

关闭 httpd: [ OK ]启动 httpd: [ OK ]

但是当我尝试在没有 sudo 的情况下执行这样的命令时

service httpd stop && service httpd start

我知道服务器说“找不到命令”或类似的东西,但我无法收到此错误,此脚本无限执行。

我试图以这种方式(或其他类似的方式)重写我的代码

    $dataString = fgets($stdout_stream);
        if($dataString == "\n" || $dataString == "\r\n" || $dataString == "") {
            //var_dump("Empty line found.");
        }

        if($dataString === false && !feof($stdout_stream)) {
            //var_dump("not string");
        } elseif($dataString === false && feof($stdout_stream)) {
            //var_dump("We are at the end of the file.\n");
            break;
        } else {
            //else all is good, process line read in
            $output .= $dataString;
        }
    }

但结果是一样的。

所以问题是我们不能事先说出是什么原因导致了无限循环或.$stdout_stream$stderr_stream

我正在使用 PHP 5.3。

php feof ssh2-exec

评论

0赞 Answers_Seeker 4/23/2015
在代码的重写版本中,您是否总是遇到“$output.=”情况或发生其他情况?如果是 sudo 有什么不同,你能做权限检查吗?一般来说,无限循环可能是由错误的“停止标准”(“停止情况”、“cas d'arrêt”)或错误的增量/步骤到下一次迭代引起的。也许回答这些问题会对你有所帮助。祝你好运
0赞 Alexandr Suleymanov 4/24/2015
感谢您的回复。有时返回 false,即使命令最终成功执行,所以这就是为什么当我知道命令不会很好地执行时我不能指望它的原因。Auth_User具有重新启动 httpd 服务的权限。fgets($stdout_stream)
0赞 Answers_Seeker 4/24/2015
“www-data”是“Auth_User”组的一部分吗?如果没有,也许给 www-data 执行 httpd 的权限就可以了。(乔恩)
0赞 Alexandr Suleymanov 4/24/2015
谢谢,我会检查这个选项,但是将 sudo 添加到我的命令中对我来说不是问题,兴趣是为什么ssh2_exec似乎返回了良好的响应(流类型的资源),但脚本不能做任何可以接受的事情。我猜它无法到达文件末尾,但实际上不知道问题是什么。
0赞 Answers_Seeker 4/24/2015
你能加入你的流的var_dump()吗?在循环播放之前,有什么方法可以将 EOF (chr(26)) 字符连接到流的末尾?

答:

0赞 Alexandr Suleymanov 4/24/2015 #1

我决定相信我的服务器有足够的 ~2 秒来检查是否存在错误。以防万一,为 secod 循环设置最大时间。所以我的代码如下。它的执行力比我想要的要多......

    try {
        $stdout_stream = ssh2_exec($this->connection, $_cmd);
        $stderr_stream = ssh2_fetch_stream($stdout_stream, \SSH2_STREAM_STDERR);
    } catch (Exception $e) {
        $std_output = $e->getMessage();
        return false;
    }

    $output = "";

    $start_time = time();
    $max_time = 2; //time in seconds

    while(((time()-$start_time) < $max_time)) {
        $output .= fgets($stderr_stream, 4096);
    }

    if(empty($output)) {
        $start_time = time();
        $max_time = 10; //time in seconds

        while (!feof($stdout_stream)) {
            $output .= fgets($stdout_stream, 4096);
            if((time()-$start_time) > $max_time) break;
        }
    }

    fclose($stdout_stream);
    fclose($stderr_stream);     

    return $output;
0赞 Jared Brandt 2/3/2020 #2

男孩,我很高兴我找到了这个!我遇到了同样的问题。我最终以这种方式解决了它。

而不是:

while (!feof($stdout_stream)) {
    $output .= fgets($stdout_stream, 4096);
}

while (!feof($stderr_stream)) {
    $output .= fgets($stderr_stream, 4096);
}

执行此操作:

while (!feof($stdout_stream) || !feof($stderr_stream)) {
    $output_stdout .= fgets($stdout_stream, 4096);
    $output_stderr .= fgets($stderr_stream, 4096);
}

技术细节超出了我的范围,但似乎两个描述符同时关闭,而不是一次关闭一个。