JSch Channel.getExitStatus 没有 return 在 "shell" 通道中执行的命令的状态

JSch Channel.getExitStatus does not return status of command executed in "shell" channel

我正在尝试通过 JSch – diff 命令比较文件。 我想通过 Java 代码获取状态以了解文件是否等于,即 echo $status。 我怎样才能在 java 中做到这一点?

这是我的 class 到 运行 SSH 命令

public class SSH {

    static Logger logger = LogManager.getLogger("sshLogger");
    static Process p;
    static String s;
    int exitStatus = -1;
    String user;
    String pass;
    String server;
    String command;
    public Channel channel;
    public Session session;
    public InputStream in;

    public SSH(String user, String pass, String server) {
        this.user = user;
        this.pass = pass;
        this.server = server;
        logger.debug("instance: " + user + "@" + server);
    }

    private Session getConnectedSession(String user, String pass, String server) throws JSchException {

        session = new JSch().getSession(user, server, 22);
        java.util.Properties config = new java.util.Properties();
        session.setPassword(pass);
        config.put("StrictHostKeyChecking", "no");
        config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
        session.setConfig(config);

        logger.debug("get connected session at: " + server);
        session.connect();
        logger.debug("connected to session");

        return session;

    }

    public Channel getChannel() {

        // ByteArrayOutputStream byteArrOutSt = new ByteArrayOutputStream();

        try {
            session = getConnectedSession(user, pass, server);
            logger.debug("opening channel at: " + server);
            channel = session.openChannel("shell");
        } catch (JSchException e) {
            logger.error("failed to connect to: "+ user + "@"+ server);
            e.printStackTrace();
        }
        // channel.setOutputStream(baos);
        channel.setOutputStream(System.out);
        channel.setExtOutputStream(System.out, true);
        // channel.setPty(Boolean.FALSE);

        return channel;

    }

    public String commandBuilder(String... commands)  {

        StringBuilder commandString = new StringBuilder();
        for (String command : commands) {
            logger.debug("adding command: " + command);
            commandString.append(command + "\n");
        }
        logger.debug("adding command: exit");
        commandString.append("exit\n");
        String myCommand = commandString.toString().replace("\n", "\n");
        return myCommand;
    }
    
    
    public String executeCommand(String myCommand) {
        channel = getChannel();
        //String finishedCommand = commandBuilder(myCommand);
        logger.debug(myCommand);
    
        StringBuilder outBuff = new StringBuilder();
        String outComm = null;
        channel.setInputStream(new ByteArrayInputStream(myCommand.getBytes(StandardCharsets.UTF_8)));
        try {
            in = channel.getInputStream();
            channel.connect();
            // read from the output
            System.out.println("printing");
            while (true) {
                for (int c; ((c = in.read()) >= 0);) {
                    outBuff.append((char) c);
                }

                if (channel.isClosed()) {
                    if (in.available() > 0)
                        continue;
                    exitStatus = channel.getExitStatus();
                    break;
                }
            }
        } catch (IOException e) {
            logger.error("failed while running or reading output of command: " + myCommand);
        } catch (JSchException e) {
            
            logger.error("failed to connect to server while running command: " + myCommand);
        }
        

        logger.info(outBuff.toString());
        return outBuff.toString();
    }

    
    public void endSession() {

        logger.debug("ending session");
        channel.disconnect();
        session.disconnect();
        logger.debug("disconnected channel and session");

        // print exit status
        logger.debug("Exit status of the execution: " + exitStatus);
        if (exitStatus == 0) {
            logger.debug(" (OK)\n");
        } else {
            logger.debug(" (NOK)\n");
        }
    }
    
    public String runCommand(String... commands) {
        
        // many commands as you want
        
        
        String output = null;
        String myCommands;
        myCommands = commandBuilder(commands);
        try {
            output = executeCommand(myCommands);
            endSession();
        } catch (Exception e) {
            logger.error("failed to run ssh comands: "+ commands);
            e.printStackTrace();
        } 
        return output;
        
    }
    
}

diff 使用 SSH 示例:

SSH session = new SSH(user, pass, server);
session.runCommand("diff file1.xml file2.xml");

首先不要执行“shell”频道中的命令。 “shell”是一个只有输入和输出的黑盒子。参见 What is the difference between the 'shell' channel and the 'exec' channel in JSch

使用“exec”频道。在“exec”频道中,Channel.getExitStatus 有效。

有关代码示例,请参阅:How to read JSch command output?


强制警告:不要使用StrictHostKeyChecking=no盲目接受所有主机密钥。这是一个安全漏洞。您失去了针对 MITM attacks. For the correct (and secure) approach, see:

的保护