无法调用ssh2_connect()回调

时间:2014-08-29 07:39:24

标签: php ssh

我正在使用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;
}

我做错了什么?

4 个答案:

答案 0 :(得分:7)

当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')

答案 1 :(得分:3)

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

有解决方案(例如下面的rubo77建议),但我找到的那个会给你最大的控制权,并允许你做你想做的事情(例如跟踪MAC错误),就是使用phpseclib库({{3用于ssh连接和控制。它可以非常精细地控制命令,还包括记录。

这不是最简单的解决方案,但您可以像控制键盘/终端一样精确控制。

您可以控制超时,并可以在命令上使用回调。但是,如果您想要更好的控制,请使用read()write(),您可以监控断开连接或其他问题。检查http://phpseclib.sourceforge.net/ssh/intro.html:您可以记录并解析日志,也可以致电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'
    );

答案 2 :(得分:0)

即使您使用工作代码,例如:

$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回调例如仅在收到SSH2_MSG_DISCONNECT数据包时才会调用get。除非服务器关闭通常不会发生的连接,否则不会收到此类数据包。

答案 3 :(得分:0)

如果由于错误的凭据而无法连接,那么无论如何您都不会获得任何回调,在这种情况下,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();