Невозможно вызвать вызовы ssh2_connect()
Я использую метод 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;
}
Что я делаю неправильно?
Ответы
Ответ 1
Нет ничего, что вы делаете неправильно, кроме опечатки: array('hostkey', 'ssh-rsa')
должно быть array('hostkey' => 'ssh-rsa')
. Функция ssh_connect()
просто возвращает false для отказа соединения; обратные вызовы просто не инициируются, когда используются неправильные учетные данные.
Существуют решения (например, как предлагается rubo77 ниже), но тот, который я нахожу, даст вам наибольший контроль и позволит вам делать то, что вы хотите (например, отслеживать ошибки MAC), использовать библиотеку phpseclib (http://phpseclib.sourceforge.net/ssh/intro.html) для соединений ssh и управления. Он обеспечивает очень точный контроль команд, а также включает в себя ведение журнала.
Это не самое простое решение, но вы можете управлять так же точно, как если бы вы были на клавиатуре/терминале напрямую.
У вас есть контроль над таймаутами и вы можете использовать обратный вызов для команд. Но если вам нужен лучший контроль, используйте read()
и write()
, и вы можете следить за отключением или другими проблемами. Проверьте документацию по протоколированию с помощью 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'
);
Ответ 2
Когда 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')
Ответ 3
Даже если вы будете использовать рабочий код, например:
$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);
}
обратные вызовы не будут вызваны в обычном приложении. Это связано с тем, что они вызывались при определенных обстоятельствах, указанных на странице
Обратный вызов disconnect
, например, вызывается только при получении пакета SSH2_MSG_DISCONNECT
. Такой пакет не принимается, если сервер не закрывает соединение, которое обычно не будет выполняться.
Ответ 4
Если вы не можете подключиться из-за неправильных учетных данных, вы все равно не получите никаких обратных вызовов, 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();