java - JSch 问题 - 无法检索完整的命令输出

标签 java ssh jsch

我正在使用 JSch 连接到 SSH 并执行命令。其中一个命令给出了一个很大的输出。在终端中,如果执行命令,则必须按 Enter 键才能查看整个输出。使用 JSch 我无法检索整个输出。

当我使用交互式终端登录时,命令输出在填满屏幕后停止并等待 Enter

代码取自 How to get jsch shell command output in String :

public class SshConnectionManager {

    private static Session session;
    private static ChannelShell channel;
    private static String username = "";
    private static String password = "";
    private static String hostname = "";


    private static Session getSession(){
        if(session == null || !session.isConnected()){
            session = connect(hostname,username,password);
        }
        return session;
    }

    private static Channel getChannel(){
        if(channel == null || !channel.isConnected()){
            try{
                channel = (ChannelShell)getSession().openChannel("shell");
                channel.connect();

            }catch(Exception e){
                System.out.println("Error while opening channel: "+ e);
            }
        }
        return channel;
    }

    private static Session connect(String hostname, String username, String password){

        JSch jSch = new JSch();

        try {

            session = jSch.getSession(username, hostname, 22);
            Properties config = new Properties(); 
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.setPassword(password);

            System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
            session.connect();
            System.out.println("Connected!");
        }catch(Exception e){
            System.out.println("An error occurred while connecting to "+hostname+": "+e);
        }

        return session;

    }

    private static void executeCommands(List<String> commands){

        try{
            Channel channel=getChannel();

            System.out.println("Sending commands...");
            sendCommands(channel, commands);

            readChannelOutput(channel);
            System.out.println("Finished sending commands!");

        }catch(Exception e){
            System.out.println("An error ocurred during executeCommands: "+e);
        }
    }

    private static void sendCommands(Channel channel, List<String> commands){

        try{
            PrintStream out = new PrintStream(channel.getOutputStream());

            out.println("#!/bin/bash");
            for(String command : commands){
                out.println(command);
            }
            out.println("exit");

            out.flush();
        }catch(Exception e){
            System.out.println("Error while sending commands: "+ e);
        }

    }

    private static void readChannelOutput(Channel channel){

        byte[] buffer = new byte[1024];

        try{
            InputStream in = channel.getInputStream();
            String line = "";
            while (true){
                while (in.available() > 0) {
                    int i = in.read(buffer, 0, 1024);
                    if (i < 0) {
                        break;
                    }
                    line = new String(buffer, 0, i);
                    System.out.println(line);
                }

                if(line.contains("logout")){
                    break;
                }

                if (channel.isClosed()){
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee){}
            }
        }catch(Exception e){
            System.out.println("Error while reading channel output: "+ e);
        }

    }

    public static void close(){
        channel.disconnect();
        session.disconnect();
        System.out.println("Disconnected channel and session");
    }


    public static void main(String[] args){
        List<String> commands = new ArrayList<String>();
        commands.add("ls -l");

        executeCommands(commands);
        close();
    }
}

最佳答案

您通常不应使用“shell” channel 来自动执行命令。

“shell” channel 旨在实现交互式 shell session 。

因此它请求 PTY(伪终端),它具有对人类友好但对机器不友好的副作用,会破坏您的代码。

改用“exec” channel 。

参见Execute a list of commands from an ArrayList using JSch exec in Java

<小时/>

如果您出于某种原因需要或想要使用“shell” channel (但不这样做,无论如何它都会咬您),请确保在 之前调用 .setPty(false) .connect:

channel = (ChannelShell)getSession().openChannel("shell");
channel.setPty(false);
channel.connect();
<小时/>

旁注:

关于java - JSch 问题 - 无法检索完整的命令输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35502600/

相关文章:

java - 使用 PowerMock 抑制同一类中的 void 静态方法和静态方法

java - Lucene:多词短语作为搜索词

java - 没有应用可以处理此操作 Google Duo

通过创建执行某些工作的接口(interface)的模拟对象来进行 Java 单元测试

file - 如何在不使用 shell 命令的情况下通过 SSH 以编程方式修改文件?

windows - 将 mac 上生成的 ssh key 转换为 ppk

python - Python subprocess.Popen运行ssh的结果异常

unix - 如何一次性运行多个 Unix 命令

java - Expect4j 不等待完整输出

java - 通过Java中的SSH隧道连接到Mongo数据库