如何使用相同的shell通过JSCH执行多个unix命令?

时间:2014-03-07 15:42:58

标签: java ssh jsch

我想通过我的java程序从ssh执行多个命令。基于执行结果,我需要在同一个shell上执行更多命令。但是当我试图执行它时,它采取了不同的shell。如果有人知道分辨率非常受欢迎。

这是我的代码段

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 个答案:

答案 0 :(得分:1)

每次拨打getSession()时,您都会收到新会话。这就是为什么每个命令都在不同的shell中执行的原因,因为它是一个不同的shell。

相反,在main()中进行一次会话,保留该对象。然后重复使用它。

除了getSession()之外,你需要一个不同的方法,更不用说“get session”对于在远程shell上执行命令的方法来说不是一个好名字...即。这不只是一个会议,而是做其他事情。这违反了最不惊讶的原则,即。每种方法都应该只做一件事。

创建一个新方法,称为:executeRemoteCommand(String command)并使用它来执行命令。您可以使用getSession()一次,并将会话存储在可从每个方法访问的对象中,即。实例变量。或者您可以将会话传递到executeRemoteCommand()方法。就像:executeRemoteCommand(Session session, String command)

这是我过去如何做到这一点的一个例子(不会假装这个代码是完美的......但它应该给你一些想法)。这用于通过sFTP从linux服务器发送和接收文件。通过一些修改,它可以将任何命令发送到您想要的远程shell。

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

    }

}