2013-04-21 7 views
10

Ich schreibe Java GUI Programm für die statische Routenverwaltung mit SSH. Mein Code ist wie folgt:JSch: Wie man die Session am Leben hält und weiter geht

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); 
     } 
    } 
}  

Das Problem ist, wenn ich die connect-Methode aufrufen und dann die addRoute Aufruf, kehrt das Programm

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

Ich habe versucht, mit dem Sitzungsstatus zu erhalten entweder

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

oder

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

Ich habe auch versucht, Keepalive zu verwenden, aber es funktioniert auch nicht.

Meine Absicht ist es, eine Sitzung zu erstellen (anmelden), während die Sitzung verlassen, einen Befehl oder Befehle ausführen und später möglicherweise andere Befehle ausführen und dann die Sitzung schließen, wenn sie nicht benötigt wird (abmelden). Ich habe in diesem Forum gesucht und ich fand diese question, aber der Code ist eine Methode zum Definieren eines Befehls erstellen, um zuerst auszuführen, und erstellen Sie dann die Sitzung, rufen Sie die Methode des Befehls und schließen Sie die Sitzung.

Irgendwelche Ideen wie zu tun, wie ich oben erwähnt?

Antwort

10

Nach Session.sendKeepAliveMsg() ohne Erfolg versucht, kam ich auf die folgende Lösung, die recht stabil zu sein scheint:

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; 
} 

Update: Einige Tage später schlug fehl.

Ich habe versucht, es zu testen, indem Sie die geöffnete Sitzung auf dem Server beenden. Alle früheren Versionen, die ich auf diese Weise getestet habe, zeigten das gleiche Verhalten, unabhängig davon, ob das Problem nach einigen Tagen des Wartens auftrat oder den Serverprozess beendete. Daher hielt ich diesen Test - und das Ergebnis für die obige Lösung - für sinnvoll. Leider ist es nicht.

Ich werde versuchen, einige andere Möglichkeiten, um es zu beheben und halten Sie auf dem Laufenden.

Update 2: Endlösung, guarateed unelegant und Arbeiten:

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; 
} 

Diese Version mehrere Wochen in einer produktiven Umgebung ausgeführt wird. Einmal am Tag habe ich die Info-Nachricht protokolliert.

Die Kosten für das Öffnen eines Kanals und das Ausführen von Do-nothing-Befehlen sind etwas nervig, aber ich habe keine andere Möglichkeit gefunden, über den Zustand der Sitzung sicher zu sein.

+0

nette Lösung, nur ein Tipp: Ich würde 'testChannel.exit();' nach erfolgreicher Prüfung hinzufügen, sonst Sie am Ende mit einem weiteren sftp-Server Daemon Prozesse auf der Server-Seite für jede Prüfung – GWu

+0

Vielen Dank.'TestChannel.exit() 'hinzugefügt. – blafasel

+0

Ich hatte Deadlock-Probleme beim Öffnen mehrerer Kanäle. GetSession() 'synchronized' hat dies gelöst, aber es ist ein bisschen ein Performance-Hit. Weißt du, welcher Teil synchronisiert werden muss? Vielleicht ist der Testkanal connect = disconnect? –