我正在使用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;
}
我做错了什么?
答案 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();