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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22254466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 14:34:30  来源:igfitidea点击:

How to execute multiple unix command through JSCH using same shell?

javasshjsch

提问by Sachin

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.

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

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

    }

}
`

回答by SnakeDoc

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.

每次调用 时都会获得一个新会话getSession()。这就是为什么每个命令都在不同的 shell 中执行的原因,因为它是一个不同的 shell。

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

相反,在您的 中获取您的会话main(),保留该对象。然后重新使用它。

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.

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

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).

创建一个新方法,例如调用:executeRemoteCommand(String command)并使用它来执行您的命令。您可以使用getSession()一次并将会话存储在每个方法都可以访问的对象中,即。一个实例变量。或者您可以将会话传递到您的executeRemoteCommand()方法中。所以喜欢: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.

这是我过去如何做到这一点的一个例子(不会假装这段代码是完美的......但它应该给你一些想法)。这用于通过 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");

    }

}