it-swarm.com.de

JSch: Wie man die Sitzung am Leben erhält

Ich schreibe ein Java-GUI-Programm für die Verwaltung statischer Routen mit SSH. Mein Code lautet wie folgt:

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 und dann die addroute aufrufe, das Programm zurückgibt

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

Ich habe versucht, mit beiden den Sitzungsstatus zu erhalten

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 für den Host zu erstellen (Anmelden), während die Sitzung beendet wird, einen oder mehrere Befehle auszuführen und möglicherweise andere Befehle später auszuführen und die Sitzung dann zu schließen, wenn sie nicht benötigt wird (Abmelden). Ich habe in diesem Forum gesucht und diese Frage gefunden, aber der Code besteht darin, eine Methode zum Definieren eines Befehls zu erstellen, der zuerst ausgeführt werden soll, und dann die Sitzung zu erstellen, die Methode des Befehls aufzurufen und die Sitzung zu schließen.

Irgendwelche Ideen, wie ich vorhin darauf eingegangen bin?

11
user2277956

Nachdem ich Session.sendKeepAliveMsg() erfolglos ausprobiert hatte, kam ich zu der folgenden Lösung, die ziemlich 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 ist es fehlgeschlagen.

Ich habe versucht, es zu testen, indem ich die offene Sitzung auf dem Server beendet habe. Alle früheren Versionen, die ich auf diese Weise getestet habe, zeigten genau dasselbe Verhalten, unabhängig davon, ob das Problem nach einigen Tagen Warten oder Beenden des Serverprozesses aufgetreten ist. Daher hielt ich diesen Test - und dessen Ergebnis für die obige Lösung - für sinnvoll. Leider ist es nicht.

Ich werde versuchen, es auf andere Weise zu beheben und Sie auf dem Laufenden zu halten.

Update 2: Endgültige Lösung, garantiert unelegant und funktioniert:

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 läuft mehrere Wochen in einer produktiven Umgebung. Einmal am Tag habe ich die Infomeldung protokolliert.

Die Kosten für das Öffnen eines Kanals und das Ausführen von Do-nothing-Befehlen sind etwas ärgerlich, aber ich habe keine andere Möglichkeit gefunden, um den Status der Sitzung genau zu bestimmen.

14
blafasel

Sie können versuchen, indem Sie die folgende Methode aufrufen, bevor Sie Session # connect () aufrufen.

Session # setServerAliveInterval (int Millisekunden)

Obwohl ich noch eine Funktion gefunden habe Session # sendKeepAliveMsg () die ausprobiert werden kann.

5
Garry

Sie können einen Pool verwenden, ich habe org.Apache.commons.pool2 verwendet, sodass der Pool für die Bereitstellung verbundener Sitzungen verantwortlich ist.

  • Erstellen Sie eine JSCH-Sitzung auf makeObject
  • connect on activate wenn nicht verbunden
  • Überprüfen Sie bei der Überprüfung, ob isConnected ist
  • sendKeepAliveMsg bei Passivierung

Denken Sie auch daran, dass, wenn Sie beim Überprüfen Logik hinzufügen, poolConfig bei testOnBorrow oder testOnReturn auf true gesetzt werden sollte. Also habe ichKeyedObjectPoolverwendet. Sie sollten Verbindungen überborrowObjectaus dem Pool abrufen und sicherstellen, dass Sie sie nach der Operation wieder in den Pool zurückgeben ist abgeschlossen überreturnObject.

https://commons.Apache.org/proper/commons-pool/api-2.2/org/Apache/commons/pool2/PooledObjectFactory.html

0
Ringuerel