JSch: How to keep the session alive and up

前端 未结 3 702
攒了一身酷
攒了一身酷 2020-12-08 11:05

I\'m writing Java GUI program for static route management using SSH. My code is as follows:

import com.jcraft.jsch.*;
import java.io.*;

public class Konsep          


        
相关标签:
3条回答
  • 2020-12-08 11:45

    You can use a pool , I used org.apache.commons.pool2 so the pool is responsible of providing connected sessions, basically:

    • Create JSCH Session on makeObject
    • connect on activate if disconnected
    • check if isConnected on validate
    • sendKeepAliveMsg on passivate

    Above worked for me, also keep in mind that if you add logic on validate, the poolConfig should set true on testOnBorrow or testOnReturn. So I used KeyedObjectPool you should get connections from the pool via borrowObject method and make sure you return them to the pool once you operation is complete via returnObject.

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

    0 讨论(0)
  • 2020-12-08 11:50

    You can try by invoking the following method before invoking Session#connect().

    Session#setServerAliveInterval(int milliseconds)

    Although I found one more function Session#sendKeepAliveMsg() which can be tried.

    0 讨论(0)
  • 2020-12-08 11:55

    After trying Session.sendKeepAliveMsg() without success, I came to the following solution which seems to be rather stable:

    private Session getSession() throws Exception {
        try {
            if (!session.isConnected()) {
                logger.info("Session successfully tested, use it again.");
                session.connect();
            }
        } catch (Throwable t) {
            logger.info("Session terminated. Create a new one.");
            session = jsch.getSession(user, host, port);
            session.setConfig(config);
            session.connect();
        }
        return session;
    }
    

    Update: Some days later it failed.

    I tried to test it by killing the open session on the server. All prior versions I tested this way showed the exact same behavior, regardless whether the problem popped up after waiting some days or killing the server process, so I thought this test - and its outcome for the above solution - to be meaningful. Unfortunately, it isn't.

    I'm going to try some other ways to fix it and keep you up to date.

    Update 2: Final solution, guaranteed inelegant and working:

    private Session getSession() throws Exception {
        try {
            ChannelExec testChannel = (ChannelExec) session.openChannel("exec");
            testChannel.setCommand("true");
            testChannel.connect();
            if(logger.isDebugEnabled()) {
                logger.debug("Session successfully tested, use it again.");
            }
            testChannel.exit();
        } catch (Throwable t) {
            logger.info("Session terminated. Create a new one.");
            session = jsch.getSession(user, host, port);
            session.setConfig(config);
            session.connect();
        }
        return session;
    }
    

    This version runs several weeks in a productive environment. Once a day I have the info message logged.

    The costs of opening a channel and performing some do-nothing-command are somewhat annoying, but I found no other way to be definitely sure about the state of the session.

    0 讨论(0)
提交回复
热议问题