【问题标题】:unable to call ssh2_connect() callbacks无法调用 ssh2_connect() 回调
【发布时间】:2014-10-23 04:40:47
【问题描述】:

我正在使用ssh2_connect() 方法与远程服务器建立连接。如果我提供正确的主机名和端口号,则连接建立正确。当由于凭据错误而无法连接时,我正在尝试调用回调函数,但我尝试它的方式不是在连接失败后调用回调。

这是我尝试过的代码:

$callbacks = array( 
      'ignore' => array($this, 'callbackSshDisconnect'), 
      'debug' => array($this, 'callbackSshDisconnect'), 
      'macerror' => array($this, 'callbackSshDisconnect'), 
      'disconnect' => array($this, 'callbackSshDisconnect'), 
);

ssh2_connect($hostName,$port,array('hostkey', 'ssh-rsa'),$callbacks);

public function callbackSshDisconnect($reason, $message, $language) {
    $this->log('disconnected');
    $this->log($reason);die;
}

我做错了什么?

【问题讨论】:

  • 我想你想要的是array('hostkey' => 'ssh-rsa')

标签: php ssh


【解决方案1】:

除了错字之外,您没有做错任何事情:array('hostkey', 'ssh-rsa') 应该是 array('hostkey' => 'ssh-rsa')。函数ssh_connect() 只是在连接失败时返回false;当使用了错误的凭证时,回调根本就没有启动。

有一些解决方案(例如下面的 rubo77 所建议的),但我发现的一个解决方案是使用 phpseclib 库(http://phpseclib.sourceforge.net/ssh/intro.html ) 用于 ssh 连接和控制。它可以很好地控制命令,还包括日志记录。

这不是最简单的解决方案,但您可以像直接在键盘/终端上一样进行精细控制。

您可以控制超时,并且可以对命令使用回调。但如果您想要更好的控制,请使用read()write(),您可以监控断开连接或其他问题。查看documentation on logging with phpseclib:可以记录并解析日志,也可以调用getLastError()

例如,日志文件会在断开连接时显示'Connection closed by server',但还会告诉您是否在登录等时使用了不受支持的身份验证模式。

或者更多,请阅读代码:例如,这里是断开连接的原因:

    $this->disconnect_reasons = array(
        1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT',
        2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR',
        3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED',
        4 => 'NET_SSH2_DISCONNECT_RESERVED',
        5 => 'NET_SSH2_DISCONNECT_MAC_ERROR',
        6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR',
        7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE',
        8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED',
        9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE',
        10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST',
        11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION',
        12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS',
        13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER',
        14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE',
        15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'
    );

【讨论】:

  • @rubo77:按照建议展开。谢谢。
  • 不需要提示其他答案,只要假设你的答案是这里唯一的答案,请随时再次增强我的语法
  • 目的是帮助 OP 编程正确的解决方案,而不是总是回答具体问题。因此,当我添加其他答案时,我总是将其归功于其他答案(如果它们是正确的)。然而,在这种情况下,我没有意识到你提供了赏金(虽然现在有,谢谢)。但是,由于您显然在寻求比您自己更好的解决方案,希望这会有所帮助。作为提示,如果您正在实施,请查看“sudo”(高级交互部分)的说明,因为当您开始使用它时,您基本上就在路上了。否则深入代码;它很容易阅读。
  • 谢谢@rubo77 我对回调有误解。我在想每次由于凭据而出现连接问题时都会调用回调。
【解决方案2】:

当您由于错误的凭据而无法连接时,无论如何您都不会收到任何回调,在这种情况下 ssh2_connect() 只会返回 false

如果你真的想捕捉失败的原因,你可以使用输出缓冲区处理程序来提取错误消息(假设你设置了错误报告):

set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) {
    list($command,$errormessage)=explode(":",$errstr,2);
    echo "Error ($errno):", $errormessage."<br><br>";
});
$connection = ssh2_connect($hostName,$port);
restore_error_handler();

【讨论】:

    【解决方案3】:

    即使你会使用 working 代码,像这样:

    $callbacks = array(
        'ignore' => 'callback',
        'debug' => 'callback',
        'macerror' => 'callback',
        'disconnect' =>'callback',
    );
    
    $session = ssh2_connect($hostName, $port, array('hostkey' => 'ssh-rsa'), $callbacks);
    if($session === false) {
        print('Connection failed' . PHP_EOL);
        exit(1);
    }
    
    if(!ssh2_auth_pubkey_file(
        $session,
        "user",
        '/home/user/.ssh/id_rsa.pub',
        '/home/user/.ssh/id_rsa'
    )) {
        print('Failed to authenticate session' . PHP_EOL);
        exit(2);
    }
    
    // Check this great answer:
    // http://stackoverflow.com/a/12094837/171318
    $stream = ssh2_exec($session, "ls -al");
    stream_set_blocking($stream, true);
    $stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
    echo stream_get_contents($stream);  
    
    function callback($reason, $message, $language) {
        print("callback:" . PHP_EOL);
        print(" " . $message . PHP_EOL);
        print(" " . $reason . PHP_EOL);
    }
    

    回调不会在通常的应用程序中被调用。这是因为它们只是在manual page中命名的特定情况下被调用

    disconnect 回调例如 get 仅在收到 SSH2_MSG_DISCONNECT 数据包时调用。除非服务器关闭通常不会发生的连接,否则不会收到这样的数据包。

    【讨论】:

      【解决方案4】:

      当 ssh2_connect 因为错误的主机、端口等原因失败时,它不会调用任何回调。

      相反,它的作用是返回 false

      PHP 文档说:
      成功返回资源,错误返回 FALSE。

      $result = ssh2_connect($hostName,$port,array('hostkey' => 'ssh-rsa'),$callbacks);
      if ($result === false)
         exit("ssh2_connect failed");
      

      另外,阅读文档,你的

      array('hostkey', 'ssh-rsa')
      

      应该是

      array('hostkey' => 'ssh-rsa')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-23
        • 2011-09-21
        • 1970-01-01
        • 2019-09-21
        • 2022-10-15
        • 1970-01-01
        • 1970-01-01
        • 2015-09-30
        相关资源
        最近更新 更多