Linux命令执行后读取输出将进入无限循环

问题描述 投票:-1回答:2

我正在从jsch执行cmd,一旦命令完成,我需要显示命令输出。在读取命令输出时,即使在执行命令之后,它也会花费很长时间并且它不会来自while循环。以下是我的代码:

java.util.Properties config = new java.util.Properties(); 
        config.put("StrictHostKeyChecking", "no");


        JSch jsch = new JSch();
        session=jsch.getSession(user, host, 22);
        session.setConfig("PreferredAuthentications","publickey,keyboard-interactive,password");
        session.setPassword(password);

        session.setConfig(config);
        session.connect();
        System.out.println("Connected");

        channel=session.openChannel("shell");
        OutputStream ops = channel.getOutputStream();
        PrintStream ps = new PrintStream(ops, true);

         channel.connect();
         ps.println(cmd);
        InputStream in=channel.getInputStream();
        byte[] tmp=new byte[1024];
        while(channel.getExitStatus() == -1){
          while(in.available()>0){
            int i=in.read(tmp, 0, 1024);
            if(i<0)break;
            System.out.print(new String(tmp, 0, i));
          }
          if(channel.isClosed()){
            System.out.println("exit-status: "+channel.getExitStatus());
            break;
          }
          try{Thread.sleep(3000);}catch(Exception ee){}
        }
java linux java-ee java-io jsch
2个回答
1
投票

从我到目前为止观察到的情况来看,只有在SSH守护程序向您发送输出流的所有内容(stdout和stderr)后,channel.isClosed()才会成立。

如果此内容很大,它将无法完全适合sshd与您的进程之间的TCP连接缓冲区,并且该通道将永远保持打开状态。当你在stdout和stderr中都有很多内容时问题更加严重,因为你不知道优先使用哪个流。对read()的调用是阻塞而没有超时的可能性。

我们使用的解决方案是在主线程中同时小心地消耗stdout和stderr的所有内容,如果我们不确定它是否会阻塞,则不要在任何流上调用read()

        StringBuilder result = new StringBuilder();
        StringBuilder error = new StringBuilder();

        InputStream out = channel.getInputStream();
        InputStream err = channel.getErrStream();

        while(!channel.isClosed() || out.available() > 0 || err.available() > 0) {
            if (out.available() > 0) {
                size = out.read(cbuf);
                if (size > 0) {
                    result.append(new String(cbuf, 0, size));
                } 
                // normally the 'if' is useless as available() guarantee size > 0
                // it's just an extra-precaution
            } else if (err.available() > 0) {
                size = err.read(cbuf);
                if (size > 0) {
                    error.append(new String(cbuf, 0, size));
                }
            } else {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }

0
投票

我在命令末尾添加了exit命令。

© www.soinside.com 2019 - 2024. All rights reserved.