Как уменьшить время ожидания ssh.net, когда мой ssh-клиент отключается от ssh-сервера?

Я написал небольшую программу на C#, используя ssh.net, которая подключается к серверу SSH, вносит некоторые изменения и перезапускает службу SSHD на сервере SSH.

К сожалению, сервер SSH работает на медленной встроенной системе, а служба SSHD не перезапускается достаточно быстро, чтобы сделать это плавно (без отключения клиента). На самом деле для перезапуска службы SSH требуется около минуты. Это отлично.

Мой код выглядит так:

Console.WriteLine("Restarting SSHD service on modem...");

try
{
    using (var client = new SshClient(IPAddress, "root", "PASSWORD"))
    {
        client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(10);
        client.Connect();

        client.RunCommand("service sshd restart");

        client.Disconnect();
    }
}
catch (System.Net.Sockets.SocketException)
{
    //We got disconnected because we just restarted the sshd service
    //This is expected
    Console.WriteLine("\tSuccess");
}
catch
{
    //We got disconnected for some other reason
    Console.WriteLine("\tIt appears there was a problem restarting the sshd service");
}

Проблема, с которой я сталкиваюсь, заключается в том, что клиенту ssh требуется до минуты, а иногда и больше, чтобы выяснить, что сервер SSH больше не отвечает, и выдать исключение System.Net.Sockets.SocketException. Есть ли способ сократить этот тайм-аут? Я не хочу, чтобы он переподключался - я просто хочу, чтобы он быстрее выдал исключение. Будет ли это какое-то конкретное значение тайм-аута ssh.net или тайм-аут System.Net.Sockets?


person Tal    schedule 25.03.2016    source источник
comment
Я не уверен, что удаленный сервер с коробкой Linux, у меня есть перезапуск службы, не уничтожает существующие клиентские соединения, вы установили TCPKeepAlive или ServerAliveInterval и т. Д., Чтобы убедиться, что соединение не прервется из-за медленной команды? У меня сложилось впечатление, что без настройки поддержки активности соединение будет разорвано примерно через 1 минуту, что соответствует тому, что вы видите.   -  person Hang    schedule 25.03.2016
comment
Единственные релевантные значения, которые я нашел в своем объекте SshClient, — это client.KeepAliveInterval и client.ConnectionInfo.RetryAttempts. KeepAliveInterval звучит как другое название TCPKeepAlive, поэтому я попытался установить его на 10 секунд, но это не дало никакого эффекта. Я также установил для RetryAttempts значение 1, но это тоже не имело никакого эффекта — для создания исключения по-прежнему требуется больше минуты. Есть ли другое место, где я могу установить TCPKeepAlive и ServerAliveInterval?   -  person Tal    schedule 25.03.2016
comment
Может быть, этот: fredericiana.com/2009/10/21 /   -  person Hang    schedule 25.03.2016
comment
Ссылка касается настройки сервера ssh для отправки сообщений поддержки активности клиентам, чтобы сеанс не прерывался. Я хочу, чтобы сессия падала быстрее. Я также не могу изменить sshd_config сервера ssh, поскольку я имею дело с сотнями SSH-серверов, и изменение sshd_config на всех из них заранее невозможно.   -  person Tal    schedule 25.03.2016
comment
Можете ли вы выполнить ручной перезапуск службы sshd с сервера, чтобы убедиться, что он прерывает клиентское соединение? Я хочу сказать, что SSH-сервер не должен убивать клиента, это связано с тем, что перезапуск службы занимает больше минуты, что означает, что соединение простаивает более минуты, и оно было разорвано, и поэтому я предлагаю настроить конфигурацию KeepAlive. Если вы запускаете перезапуск службы на сотнях SSH-серверов, изменение конфигурации примерно то же самое (man sed и ищите -i).   -  person Hang    schedule 25.03.2016
comment
Да, в моем случае перезапуск службы sshd заставляет сервер ssh перестать слушать более минуты, и, как вы сказали, поскольку клиент так долго простаивает, он в конечном итоге отключается. Да - есть смысл настроить KeepAlive. Как бы я это сделал? Кроме того, я не вижу, как sed может помочь - sed работает только на локальном хосте (вы не можете заставить его изменить файл на 100 серверах ssh), и я не могу/не буду менять sshd_config на серверах sshd по какой-либо причине - мой единственный вариант - изменить мой код, чтобы компенсировать любые уже настроенные параметры sshd.   -  person Tal    schedule 25.03.2016
comment
Просто хочу прояснить, заставляет ssh-сервер перестать слушать более минуты, но влияет ли это на существующее соединение? Допустим, вы подключаетесь к хосту по ssh, запускаете сервисный перезапуск, вас выкинет с сервера SSH или вы все еще будете подключены после перезапуска? Давайте проясним эту часть (чтобы понять, что клиент отключился из-за слишком долгого бездействия или из-за перезапуска сервера), затем мы можем попытаться найти решение или обходной путь.   -  person Hang    schedule 26.03.2016
comment
Если бы я использовал обычный клиент SSH (клиент linux ssh или шпатлевку) для подключения к серверу ssh и перезапуска службы sshd, сеанс перестанет отвечать примерно на минуту, в течение которого я не смогу войти любые команды, и я не смогу подключиться к серверу ни с каким другим клиентом. Через минуту, в зависимости от клиента, он может возобновить сеанс (разрешить мне снова набирать текст) или может истечь время до этого.   -  person Tal    schedule 26.03.2016
comment
Вы можете установить KeepAliveInterval (например, это), чтобы клиент проверял чаще таким образом отключаться быстрее, если удаленный сервер не отвечает, если я читаю source правильно), но, судя по вашему описанию, SocketException на самом деле не означает, что операция прошла успешно, лучший способ для меня - запустить перезапуск службы в фоновом режиме, а затем проверить службу позже.   -  person Hang    schedule 26.03.2016
comment
Как указано в моем предыдущем комментарии, client.KeepAliveInterval не имел никакого эффекта. Кроме того, моей программе абсолютно нечего делать, и нет причин ждать, пока служба ssh снова начнет отвечать. Все, что я хочу, это отправить команду перезапуска службы sshd на сервер и как можно быстрее отключиться, чтобы я мог сообщить пользователю программы, что служба перезапускается.   -  person Tal    schedule 26.03.2016
comment
All I want is to send the "service sshd restart" command to the server, and disconnect as quickly as possible - вы можете сделать "service sshd restart &" или, в зависимости от дистрибутива на SSH-сервере, может быть "service sshd restart >/dev/null 2>&1 &"   -  person Hang    schedule 26.03.2016
comment
Пробовал использовать & кучу разных способов, но, как ни странно, теперь это сработало - вроде как. Я не думаю, что пытался избавиться от stdout и stderr раньше, как вы сделали выше. К сожалению, хотя это приводит к тому, что client.RunCommand возвращается очень быстро, затем он зависает в client.Disconnect() ровно на столько же времени (более минуты). Если я закомментирую client.Disconnect(), он зависнет, пытаясь вместо этого оставить оператор использования более чем на минуту. Я посмотрю, есть ли способ разорвать соединение сразу после client.RunCommand().   -  person Tal    schedule 26.03.2016


Ответы (1)


Благодаря предложениям Ханга следующий код решил проблему:

Console.WriteLine("Restarting SSHD service on modem...");

try
{
    var client = new SshClient(IPAddress, "root", "PASSWORD")
    client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(10);
    client.Connect();

    client.RunCommand("service sshd restart >/dev/null 2>&1 &");
    Console.WriteLine("\tSuccess");
}
catch (System.Net.Sockets.SocketException)
{
    //We got disconnected because we just restarted the sshd service
    //This is expected
    Console.WriteLine("\tSuccess");
}
catch
{
    //We got disconnected for some other reason
    Console.WriteLine("\tIt appears there was a problem restarting the sshd service");
}

Следует отметить следующее:

  • Строка RunCommand теперь использует >/dev/null 2>&1, чтобы избавиться от stdout и stderr.
  • Строка RunCommand теперь использует & для запуска команды в фоновом режиме.
  • Блок try теперь содержит Console.WriteLine("\tSuccess");, потому что это наиболее вероятный результат RunCommand() — тот факт, что он будет продолжать работать, а не генерировать какие-либо исключения.
  • Больше нет оператора client.Disconnect() или using, поэтому ничто не пытается отключиться от сервера ssh — код просто продолжает работать.

Причина, по которой это работает в моем случае, заключается в том, что моя программа больше ничего не делает после этого - она ​​просто завершает работу. Другие могут захотеть подождать, пока SshClient снова станет доступным, и правильно отключиться, чтобы очистить и освободить ресурсы.

person Tal    schedule 26.03.2016