2

I want to execute multiple commands from on ssh through my java program. Based on execution result i need to execute some more commands on same shell. But when i tried to execute it is taking different shell. If any one knows the resolution is much appreciated.

Here is my code snippet

public class sshconnectionTest {
    JSch jsch = new JSch();
    Session session;
    Channel channel;

    public Session openSession() throws Exception {

        if (null == session) {
            session = jsch.getSession("user", "hostname",
                    22);

            System.out.println("**************************************"
                    + session.isConnected());

            AESencrp aesEncrypt = new AESencrp();

            session.setPassword("pwd");
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect(10 * 1000);

        }
        return session;
    }

    public Channel openChannel(Session session) throws Exception {

        if (null == channel) {
            channel = session.openChannel("exec");
        }

        return channel;
    }

    public String getSession(String command1) throws Exception {

        try {

            session = openSession();
            channel = openChannel(session);

            Channel channel = session.openChannel("exec");
            ((ChannelExec) channel).setCommand(command1);
            channel.setInputStream(null);
            ((ChannelExec) channel).setErrStream(System.err);

            InputStream in = channel.getInputStream();
            channel.connect();
            byte[] tmp = new byte[1024];
            String readText = "";
            while (true) {
                while (in.available() > 0) {
                    int i = in.read(tmp, 0, 1024);
                    if (i < 0)
                        break;
                    readText = new String(tmp, 0, i);

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

        } catch (Throwable t) {
            System.out.println(t);
        }
        return null;

    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            sshconnectionTest sshcon = new sshconnectionTest();
            String command1 = " env | grep CCM;";
            String session = sshcon.getSession(command1);
            String command = "export SRL_FILE=/home/20140224/myfile.txt;";
            sshcon.getSession(command);
            sshcon.getSession("env | grep SRL;");
            sshcon.getSession("pwd");
        } catch (Exception e) {
        }

    }

}
`

1 Answer 1

1

You are getting a new session every time you call getSession(). This is why every command is being executed in a different shell, because it is a different shell.

Instead, get your session once in your main(), keep that object. Then re-use it.

You will need a different method other than getSession(), not to mention "get session" is not a good name for a method which is executing commands on a remote shell... ie. it's not just getting a session, but doing something else. This violates the principal of least astonishment, ie. each method should do one and only one thing.

Create a new method, say called: executeRemoteCommand(String command) and use that to execute your commands. You could either use getSession() once and store the session in an object that is accessible from every method, ie. an instance variable. Or you can pass your session into your executeRemoteCommand() method. So like: executeRemoteCommand(Session session, String command).

Here is an example of how I have done this in the past (not going to pretend this code is perfect... but it should give you some ideas). This was used to send and receive files from a linux server via sFTP. With some modification, it could send just about any command to the remote shell you desire.

package com.somecompany.productfeed;

import net.snakedoc.jutils.ConfigException;

import org.apache.log4j.Logger;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

public class SFTP {

    // setup logger
    private static final Logger LOG = Logger.getLogger(SFTP.class.getName());

    private JSch jsch;
    private ChannelSftp sftpChannel;
    private Session session;

    private String username;
    private String password;
    private String host;
    private int port;

    // singleton
    private volatile static SFTP instance = null;

    /**
     * Private constructor used in Singleton pattern.
     *     All variables populated via properties file upon 
     *     object instantiation. Since we only need FTP to one server,
     *     object variables are immutable after instantiation.
     * 
     * @throws ConfigException
     * @throws NumberFormatException
     */
    private SFTP() throws ConfigException, NumberFormatException {

        this.jsch = new JSch();
        this.username = Config.getInstance().getConfig("SFTP_USER");
        this.password = Config.getInstance().getConfig("SFTP_PASS");
        this.host = Config.getInstance().getConfig("SFTP_HOST");
        this.port = Integer.parseInt(Config.getInstance().getConfig("SFTP_PORT"));

    }

    /**
     * Create or Return SFTP Object using Singleton pattern.
     * 
     * @return Singleton of SFTP Object.
     * @throws NumberFormatException
     * @throws ConfigException
     */
    public static SFTP getInstance() throws NumberFormatException, ConfigException {

        if (SFTP.instance == null) {

            synchronized (SFTP.class) {

                if (SFTP.instance == null) {

                    SFTP.instance = new SFTP();

                }

            }

        }

        return SFTP.instance;

    }

    /**
     * If connection is not already open/connected, open connection.
     * 
     * @throws JSchException
     */
    public void openConnection() throws JSchException {

        LOG.info("Opening SFTP Connection");
        if (null == getSession() || ! getSession().isConnected()) {

            setSession(jsch.getSession(this.username, this.host, this.port));
            getSession().setConfig("StrictHostKeyChecking", "no");
            getSession().setPassword(this.password);
            getSession().connect();

            Channel channel = getSession().openChannel("sftp");
            channel.connect();
            setSftpChannel((ChannelSftp) channel);

        } else {

            LOG.info("SFTP Connection already open");

        }

        LOG.debug("Success");

    }

    /**
     * Closes connection.
     */
    public void closeConnection() {

        LOG.info("Closing SFTP connection");
        getSftpChannel().exit();
        getSession().disconnect();
        LOG.debug("SFTP Connection closed");

    }

    /**
     * Checks if SFTP Connection is open.
     * 
     * @return TRUE if connection is open, FALSE if connection is closed
     */
    public boolean isOpen() {

        if (getSession().isConnected()) {

            return true;

        } else {

            return false;

        }

    }

    /**
     * Gets SFTP Channel
     * 
     * @return SFTP Channel (<code>ChannelSftp</code>)
     */
    private ChannelSftp getSftpChannel() {

        return this.sftpChannel;

    }

    /**
     * Returns current <code>Session</code>
     * 
     * @return <code>Session</code>
     */
    private Session getSession() {

        return this.session;

    } 

    /**
     * Sets SFTP Channel (<code>ChannelSftp</code>)
     * 
     * @param sftpChannel Channel to set this object's <code>ChannelSftp</code>
     */
    private void setSftpChannel(ChannelSftp sftpChannel) {

        this.sftpChannel = sftpChannel;

    }

    /**
     * Sets current <code>Session</code>
     * 
     * @param session Sets this object's <code>Session</code>
     */
    private void setSession(Session session) {

        this.session = session;

    }

    /**
     * Pushes local file to remote location
     * 
     * @param local String representation of filepath + filename (ex: /some_local_directory/somefile.txt)
     * @param remote String representation of filepath + filename (ex: /some_remote_directory/somefile.txt)
     * @throws SftpException
     */
    public void push(String local, String remote) throws SftpException {

        LOG.info("Sending file: " + local + " to remote: " + remote);
        getSftpChannel().put(local, remote);
        LOG.debug("Success");

    }

    /**
     * Gets remote file to local location
     * 
     * @param remote String representation of filepath + filename (ex: /some_remote_directory/somefile.txt)
     * @param local String representation of filepath + filename (ex: /some_local_directory/somefile.txt)
     * @throws SftpException
     */
    public void get(String remote, String local) throws SftpException {

        LOG.info("Retrieving file: " + remote + " saving to: " + local);
        getSftpChannel().get(remote, local);
        LOG.debug("Success");

    }

}
Sign up to request clarification or add additional context in comments.

2 Comments

I have done the same changes but still it takes different shell. It wont retain same shell.
if you are using the same connection, session and channel, then it will be the same shell. you are doing something wrong... :/ ... take a closer look how I did it. I set the private fields once, then leave them (including the jsch, channel, and session objects. this means, every time you use that same object, it's the same.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.