简体   繁体   English

PHP ssh2_exec在空标准输出上没有功能

[英]PHP ssh2_exec no feof on empty stdout

This PHP snippet should execute a simple command via SSH (stripped down to minimal working example): 这个PHP代码段应该通过SSH执行一个简单的命令(简化为最小的工作示例):

$sshconn = ssh2_connect($HostAddr, 22);
ssh2_auth_pubkey_file($sshconn, $user, $sshkey . '.pub', $sshkey);
$stdout = ssh2_exec($sshconn, 'echo hello');
if ($stdout !== false)
{
    stream_set_blocking($stdout, true);
    while (!feof($stdout))
    {
        $proc_stdout = fgets($stdout, 3E6);
        if ($proc_stdout !== false) echo $proc_stdout;
    }
    fclose($stdout);
}

Works great as long as there is any output to stdout. 只要有任何输出到stdout,效果就很好。 However, if stdout remains empty, the loop turns into an endless loop. 但是,如果stdout保持为空,则循环将变成一个无限循环。

$stdout = ssh2_exec($sshconn, 'echo hello >&2');

How do I read the stdout properly if 如果我如何正确读取标准输出

  • stdout may be empty 标准输出可能为空
  • but stdout may also very large (several Gigabytes, impossible to slurp into a variable by a single call to stream_get_contents or the like). 但是stdout可能也很大(几个千兆字节,不可能通过一次调用stream_get_contents之类的东西而变成变量)。

Addendum: My real world code that hangs executes mysqldump with an unknown parameter. 附录:我的现实世界代码挂起执行带有未知参数的mysqldump Obviously, echo -n >&2 works as expected, although its stdout is also empty. 显然, echo -n >&2可以正常工作,尽管它的stdout也为空。

If anyone stumbles upon this too: stderr has to be read too. 如果有人也偶然发现此内容:也必须阅读stderr。

$sshconn = ssh2_connect($HostAddr, 22);
ssh2_auth_pubkey_file($sshconn, $user, $sshkey . '.pub', $sshkey);

$stdout = ssh2_exec($sshconn, 'echo Hello >&2');
if ($stdout !== false)
{
    $stderr = ssh2_fetch_stream($stdout, SSH2_STREAM_STDERR);
    stream_set_blocking($stdout, false);
    stream_set_blocking($stderr, false);
    while (!feof($stdout))
    {
            $proc_stdout = fgets($stdout, 3E6);
            if ($proc_stdout !== false) echo $proc_stdout;
            $proc_stderr = fgets($stderr, 3E6);
            if ($proc_stderr !== false) fwrite(STDERR, $stderr);
    }
    fclose($stdout); fclose($stderr);
}

The disadvantage of this is that the SSH connection is no longer usable afterwards (a further ssh2_exec cannot be executed). 这样做的缺点是SSH连接以后将不再可用(无法再执行ssh2_exec )。

A possible solution is to keep both streams blocking and read stdout and stderr non-interleaved: 一个可能的解决方案是保持流都阻塞,并且不交错读取stdout和stderr:

$stdout = ssh2_exec($sshconn, 'echo Hello >&2');
$stderr = ssh2_fetch_stream($stdout, SSH2_STREAM_STDERR);
stream_set_blocking($stdout, true);
stream_set_blocking($stderr, true);
while ($content = fread($stdout, 3E6)) echo $content;
while ($content = fread($stderr, 3E6)) fwrite(STDERR, $content);

I invite anyone who knows how to have the streams interleaved and keep the SSH connection usable to post another answer. 我邀请任何知道如何使流交错并保持SSH连接可用的人来发布另一个答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM