我正在从 jsch 执行 cmd,命令完成后我需要显示命令输出。在读取命令输出时,它需要很长时间,并且即使在执行命令之后,它的 ns 也不是来自 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){}
}
最佳答案
根据我迄今为止的观察,只有当 SSH 守护进程向您发送了输出流(stdout 和 stderr)的所有内容时,channel.isClosed()
才是 true。
如果此内容很大,它将无法完全放入 sshd 和您的进程之间的 TCP 连接的缓冲区中,并且 channel 将永远保持打开状态。当 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();
}
}
}
关于java - Linux命令执行后读取输出将陷入无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54437550/