【问题标题】:Real-time SSH output with Net_SSH (phpseclib)使用 Net_SSH (phpseclib) 的实时 SSH 输出
【发布时间】:2018-02-19 20:53:24
【问题描述】:

我使用 Net_SSH (phpseclib) 在外部服务器上执行 SSH 命令。我根本无法弄清楚如何从命令中获得实时输出。我知道如何让它在后台运行,因此它不依赖于 Apache 进程,但我不清楚如何实时显示外部输出而不是等待命令完成。

我当前的代码就像$ssh->exec('command')一样简单。

使用的PHP版本是:

[admin@ ~]$ php -v
PHP 7.1.9 (cli) (built: Sep 10 2017 11:31:06) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

【问题讨论】:

  • edit您的问题包括所有相关的源代码。了解您在远程系统上运行的命令以及是否可以更改该程序也会很有帮助。
  • 没有相关代码展示,命令不同。

标签: php ssh phpseclib


【解决方案1】:

我设法让它与 libssh2 和输出缓冲一起工作,请参见下面的示例:

$session = ssh2_connect("server.local", 22, array('hostkey'=> 'ssh-rsa' )) or die("Couldn't connect to the SSH Server.");

ssh2_auth_pubkey_file($session, "root", "/path/to/public/key.pub", "/path/to/private/key") or die("couldn't authenticate to server"); // Authenticating to the server with a ssh-key for security purposes

while (ob_end_flush()); // end all output buffers if any

$proc = ssh2_exec($session, "ping -c 40 google.nl");

echo '<pre class="scroll">';
echo "[root@server ~]# ping -c 5 google.nl\n"; // Command you will execute
while (!feof($proc))
{
    echo fread($proc, 4096); // Read the output from the command
    @ flush(); // Flushes the whole php buffer so we can output new data
}
echo "\nDone";
echo '</pre>';

别忘了 ssh2 需要 php 5.6 或更低版本,您可以在使用时将变量 $proc 中的命令替换为 $ssh-&gt;exec('command')

【讨论】:

  • 哦。如果您的外部命令需要一段时间,请将 php.ini 中的 max_execution_time 设置为更高的值,例如600(10 分钟)。
  • 问题是关于 phpseclib,而不是 libssh2。但我很欣赏这个答案,所以会投票。
  • 您可以根据需要进行修改。只要 while 部分保持不变,它就会起作用。
【解决方案2】:

我能够使用这个来让它工作:

$ssh->exec('ping 127.0.0.1', function($output) {
    echo $output;
});

为了消除您的系统配置与我的系统配置方式的差异,我将使用 Vagrant 来建立一个通用配置。为此,这是我的 Vagrantfile:

Vagrant.configure("2") do |config|
    config.vm.box = "ubuntu/trusty64"
end

我的完整 phpseclib 代码(使用 1.0.7):

<?php
include('Net/SSH2.php');

$ssh = new Net_SSH2('127.0.0.1', 2222);
$ssh->login('vagrant', 'vagrant');

$ssh->exec('ping 127.0.0.1', function($output) {
    echo $output;
});

输出的 youtube 视频:

https://youtu.be/j9-q3024eEk

如果它不起作用,则存在多种可能性。

  1. 也许您正在运行的“命令”根本不会实时转储输出。或者它可能需要 PTY 或其他东西。很难评论,因为您还没有说出您要运行的命令是什么。正如我的帖子所展示的那样,我的解决方案可以使用命令。

  2. 也许它适用于 Vagrant,但不适用于您的系统。也许您的系统已经以某种时髦的方式或其他方式进行了配置。在这种情况下,我想如果您提供 SSH 日志会有所帮助。您可以通过define('NET_SSH2_LOGGING', 2); 然后echo $ssh-&gt;getLog(); 来获得它们。将结果发布到 pastebin.com,然后发布链接。

编辑:如果您在网络服务器中运行此程序而不是在 CLI 中运行,您可能会遇到有关如何设置网络服务器的问题 - 超出 phpseclib 的问题。比如这个输出是实时的还是锁定的?:

while (true) {
    echo "test\n";
    sleep(1);
}

flush() / ob_flush() 可能会有所帮助,但最终这将取决于您使用的网络服务器(Apache、nginx 等)、您使用的 SAPI(CGI、Apache 模块等)等。

我认为这是一个“时髦的配置”。

【讨论】:

  • @WilliamD.Edwards - 它适用于我尝试过的命令。我已经大量编辑了我的答案以记录这一事实。也许您使用的任何命令的工作方式都不同。或者您的系统可能有一些搞砸的配置设置或其他东西。有关更多信息,请参阅我的更新答案。
  • 任何命令(无论是ping 还是yum update)都会失败。我非常怀疑我的系统已经“搞砸”了一些东西,我认为需要在默认的 PHP 配置中进行一些更改。
  • @WilliamD.Edwards - 您是否尝试在网络服务器/浏览器中执行此操作?我的示例是在 CLI 中。 while (true) { echo "test\n"; sleep(1); } 是否实时输出内容?如果不是,那么flush();ob_flush(); 的某种组合,否则我认为一个新的 SO 问题可能是合适的,因为该问题与 phpseclib 无关,而专注于 phpseclib 实际上可能会分散你的注意力并剥夺你其他可能更有资格帮助您的人的答案。
  • 如果您尝试在网络服务器/浏览器中执行此操作,您正在使用的网络服务器(Apache、Nginx 等)可能会产生影响,您正在使用的 PHP SAPI(CGI、 Apache 模块等)等
  • 是的,我在网络服务器中使用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-17
  • 2017-05-25
相关资源
最近更新 更多