JSch:如何保持会话活跃起来

我正在使用SSH编写用于静态路由管理的Java GUI程序。 我的代码如下:

import com.jcraft.jsch.*; import java.io.*; public class Konsep { String status; static String username; static String hostname; String inputcommand; String output; static Session session; JSch jsch = new JSch(); public String status(String stringstatus) { stringstatus = status; return stringstatus; } public String InputCommand(String inputcommandstatus) { inputcommandstatus = inputcommand; return inputcommandstatus; } public void connect(String usernamelokal, String hostnamelokal, String password, int port) { // JSch jsch=new JSch(); try { Session sessionlokal = jsch.getSession(usernamelokal, hostnamelokal, port); sessionlokal.setPassword(password); UserInfo ui = new UserInfoku.Infoku(); sessionlokal.setUserInfo(ui); sessionlokal.setTimeout(0); sessionlokal.connect(); status = "tersambung \n"; username = usernamelokal; hostname = hostnamelokal; session = sessionlokal; System.out.println(username + " " + hostname); } catch (Exception e) { System.out.println(e); status = "Exception = \n " + e + "\n"; } } public void disconnect() { // JSch jsch=new JSch(); try { Session sessionlokal = jsch.getSession(username, hostname); // System.out.println(username +" "+ hostname); sessionlokal.disconnect(); status = "wes pedhoott \n"; } catch (Exception e) { System.out.println(e); status = "Exception = \n " + e + "\n"; } } public void addRoute() { // JSch jsch=new JSch(); System.out.println(username + " " + hostname); try { Session sessionlokal = session; // =jsch.getSession(username, hostname); Channel channel = sessionlokal.openChannel("exec"); ((ChannelExec) channel).setCommand(inputcommand); channel.setInputStream(null); channel.connect(); ((ChannelExec) channel).setErrStream(System.err); InputStream in = channel.getInputStream(); channel.connect(); byte[] tmp = new byte[1024]; while (true) { while (in.available() > 0) { int i = in.read(tmp, 0, 1024); if (i < 0) break; System.out.print(new String(tmp, 0, i)); } if (channel.isClosed()) { System.out.println("exit-status: " + channel.getExitStatus()); break; } try { Thread.sleep(1000); } catch (Exception ee) { } } channel.disconnect(); } catch (Exception e) { System.out.println(e); } } } 

问题是当我调用connect方法然后调用addroute时,程序返回

 root 192.168.50.2 root 192.168.50.2 com.jcraft.jsch.JSchException: session is down 

我一直试图获得会话状态

 Session sessionlokal=session; //returns com.jcraft.jsch.JSchException: ChannelExec 

要么

 Session sessionlokal=jsch.getSession(username, hostname); //returns session is down 

我也试过使用keepalive,但它也没有用。

我的目的是创建一个主持(登录)会话,同时保持会话,执行一个或多个命令,然后执行其他命令,然后在不需要时关闭会话(注销)。 我一直在这个论坛上搜索,我发现了这个问题,但代码是创建一个方法来定义一个先执行的命令,然后创建会话,调用命令的方法并关闭会话。

关于如何做的任何想法,如上所述?

尝试Session.sendKeepAliveMsg()没有成功,我找到了以下似乎相当稳定的解决方案:

 private Session getSession() throws Exception { try { if (!session.isConnected()) { logger.info("Session nicht konnektiert. Versuche (erneut) zu konnektieren."); session.connect(); } } catch (Throwable t) { logger.info("Session kaputt. Baue neue."); session = jsch.getSession(user, host, port); session.setConfig(config); session.connect(); } return session; } 

更新:几天后失败了。

我试图通过杀死服务器上的开放会话来测试它。 以这种方式测试的所有先前版本都显示了完全相同的行为,无论是在等待几天或者杀死服务器进程之后问题都出现了问题,所以我认为这个测试 – 以及上述解决方案的结果 – 是有意义的。 不幸的是它不是。

我将尝试其他一些方法来解决它并让你保持最新状态。

更新2:最终解决方案,保证优雅和工作:

 private Session getSession() throws Exception { try { ChannelExec testChannel = (ChannelExec) session.openChannel("exec"); testChannel.setCommand("true"); testChannel.connect(); if(logger.isDebugEnabled()) { logger.debug("Session erfolgreich getestet, verwende sie erneut"); } testChannel.exit(); } catch (Throwable t) { logger.info("Session kaputt. Baue neue."); session = jsch.getSession(user, host, port); session.setConfig(config); session.connect(); } return session; } 

该版本在高效的环境中运行数周。 我每天都会记录一下信息。

打开频道和执行一些无操作命令的成本有点令人讨厌,但我发现没有其他方法可以确定会话的状态。

您可以在调用Session#connect()之前调用以下方法。

Session #setServerAliveInterval(int milliseconds)

虽然我发现了一个可以尝试的Session #sendKeepAliveMsg()函数。