【问题标题】:How to execute multiple unix command through JSCH using same shell?如何使用相同的 shell 通过 JSCH 执行多个 unix 命令?
【发布时间】:2014-03-07 15:42:58
【问题描述】:

我想通过我的 java 程序在 ssh 上执行多个命令。根据执行结果,我需要在同一个 shell 上执行更多命令。但是当我试图执行它时,它正在使用不同的外壳。如果有人知道该决议非常感谢。

这是我的代码 sn-p

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

    }

}
`

【问题讨论】:

    标签: java ssh jsch


    【解决方案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");
    
        }
    
    }
    

    【讨论】:

    • 我做了同样的改变,但仍然需要不同的外壳。它不会保留相同的外壳。
    • 如果您使用相同的连接、会话和通道,那么它将是相同的外壳。你做错了什么......:/......仔细看看我是怎么做到的。我设置了一次私有字段,然后保留它们(包括 jsch、channel 和 session 对象。这意味着,每次使用同一个对象时,它都是一样的。
    猜你喜欢
    • 2011-08-15
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    • 1970-01-01
    • 2016-10-21
    相关资源
    最近更新 更多