как принудительно закрыть незакрытые соединения Jsch ssh

Я использую Jsch и ожидаю подключения к сетевым устройствам и обновления конфигураций, смены паролей и т. д.

У меня возникла проблема, когда петлевые соединения остаются открытыми, что препятствует созданию дополнительных сеансов ssh. Я читал, что это проблема с некоторыми версиями OpenSSH и что решение заключается в обновлении sshd. К сожалению, иногда это невозможно при подключении к сетевым устройствам.

Нет ли обходного пути?

EDIT. Вот мой код. Разве я не закрываю все вручную?

JSch jSch = new JSch();
Session session = jSch.getSession("username", h.hostname);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword("password");
session.connect();
Channel channel = session.openChannel("shell");

Expect expect = new ExpectBuilder()
                .withOutput(channel.getOutputStream())
                .withInputs(channel.getInputStream(), channel.getExtInputStream())
                .withEchoOutput(System.out)
                .withEchoInput(System.err)
                .withExceptionOnFailure()
                .build();
channel.connect();
expect.expect(contains("#"));
expect.sendLine("showRules\r");
String response = expect.expect(regexp("#")).getBefore();
System.out.println("---" + response + "----");
expect.sendLine("exit\r");
expect.close();

channel.disconnect();
session.disconnect();

person Jon A    schedule 08.01.2015    source источник
comment
Проблема, на которую вы намекаете, мне ни о чем не говорит. Может быть, вы действительно могли бы показать нам код, в котором возникла проблема, и объяснить, в чем проблема.   -  person Kenster    schedule 09.01.2015
comment
В вашем отредактированном коде вы, кажется, закрываете все, когда закончите с ним. В чем проблема? Какое плохое поведение вы получаете?   -  person Kenster    schedule 10.01.2015
comment
Примерно после 180 подключений я начинаю получать сообщения об ошибках IOException: невозможно установить петлевое соединение. Когда я делаю netstat -na, на 127.0.0.1 есть сотни подключений в статусе TIME_WAIT. Пока они не закроются, я не могу больше устанавливать ssh-подключения.   -  person Jon A    schedule 10.01.2015
comment
Насколько мне известно, Jsch не открывает скрытые петлевые соединения. Можете ли вы отредактировать свой вопрос, чтобы добавить трассировку стека для одного из этих исключений? Какая строка кода на самом деле вызывает IOException?   -  person Kenster    schedule 10.01.2015
comment
Ты прав. Это похоже на проблему с Expectit. Должен ли я удалить этот вопрос или оставить его для других, чтобы помочь им узнать, что это не Jsch?   -  person Jon A    schedule 12.01.2015


Ответы (2)


Оказывается, петлевые соединения, которые не закрывались, были созданы моей IDE — IntelliJ IDEA. Когда я развернул классы на машине с UNIX и запустил ее, не было затяжных петлевых соединений и проблем с их исчерпанием.

person Jon A    schedule 06.02.2015

Вот мой ответ на тот же вопрос, заданный здесь.

Канал не закрывается сам по себе, когда не остается ввода. Попробуйте закрыть его самостоятельно после прочтения всех данных.

while (true) {
    while (inputStream.available() > 0) {
        int i = inputStream.read(buffer, 0, 1024);
        if (i < 0) {
            break;
        }
        //It is printing the response to console
        System.out.print(new String(buffer, 0, i));
    }
    System.out.println("done");

    channel.close();  // this closes the jsch channel

    if (channel.isClosed()) {
        System.out.println("exit-status: " + channel.getExitStatus());
        break;
    }
    try{Thread.sleep(1000);}catch(Exception ee){}
}

Единственный раз, когда вы собираетесь использовать цикл, который не закрывает канал вручную, — это когда у вас есть интерактивный ввод с клавиатуры от пользователя. Затем, когда пользователь выполняет «выход», это изменит «getExitStatus» канала. Если ваш цикл while(channel.getExitStatus() == -1), то цикл завершится, когда пользователь выйдет. Вам по-прежнему необходимо самостоятельно отключить канал и сеанс после того, как вы обнаружите статус выхода.

Его нет на их странице с примерами, но на сайте JSCH размещена демонстрация интерактивной клавиатуры. http://www.jcraft.com/jsch/examples/UserAuthKI.java

Даже их демонстрация, которую я использовал для подключения к системе AIX без изменения их кода... не закрывается при выходе из оболочки!

Мне пришлось добавить следующий код, чтобы заставить его правильно выйти после того, как я набрал «выход» в своем удаленном сеансе:

         channel.connect();

         // My added code begins here
         while (channel.getExitStatus() == -1){
            try{Thread.sleep(1000);}catch(Exception e){System.out.println(e);}
         }

         channel.disconnect();
         session.disconnect();
         // My Added code ends here

       }

   catch(Exception e){
     System.out.println(e);
   }
}
person Damienknight    schedule 09.01.2015
comment
Добавил мой код выше - я не полностью следую вашему предложению. Я думаю, что намеренно закрываю канал. Меня не беспокоит ожидание остальной части ввода. Что мне нужно добавить? - person Jon A; 09.01.2015
comment
Сеанс все еще может сохраняться на целевом сервере. Закрытие сеанса на стороне вашей программы не обязательно завершит сеанс на сервере. Вам нужно явно выйти из сервера с помощью команды выхода, а затем дождаться обновления статуса выхода в объект вашего канала. - person Damienknight; 12.01.2015
comment
Приведет ли это к открытым петлевым соединениям на локальной машине? - person Jon A; 15.01.2015