如何阅读JSch命令输出?

我有以下代码:

JSch jsch = new JSch(); jsch.setKnownHosts(dotSshDir + "/known_hosts"); jsch.addIdentity(dotSshDir + "/id_rsa"); Session session = jsch.getSession(userName, hostname, 22); session.connect(); ChannelExec channel = (ChannelExec) session.openChannel("exec"); channel.setCommand(command); channel.setInputStream(null); channel.setErrStream(System.err); Reader reader = new InputStreamReader(channel.getInputStream()); char[] buf = new char[1024]; int numRead; while ((numRead = reader.read(buf)) != -1) { String readData = String.valueOf(buf, 0, numRead); result.append(readData); buf = new char[1024]; } 

它试图从读者那里读取。 我该如何解决? 我如何去寻找正在发生的事情?

悬挂实际上是由于命令中的一些不平衡的引号。

对于后代,最终代码(在处理其他一些问题之后)是:

 public String call(String hostname, String[] argv) throws SubprocessException { StringBuffer result = new StringBuffer(); Session session = null; ChannelExec channel = null; try { // TODO: Emit friendly error if ~/.ssh doesn't exist. String dotSshDir = System.getProperty("user.home") + "/.ssh"; String userName = System.getProperty("user.name"); // TODO: Emit friendly error if ~/.ssh/known_hosts doesn't exist. jSch.setKnownHosts(dotSshDir + "/known_hosts"); // TODO: Emit friendly error if ~/.ssh/id_rsa doesn't exist. jSch.addIdentity(dotSshDir + "/id_rsa"); session = jSch.getSession(userName, hostname, 22); session.connect(); channel = (ChannelExec) session.openChannel("exec"); channel.setCommand(Joiner.on(" ").join(argv)); channel.setInputStream(null); InputStream stdout = channel.getInputStream(); InputStream stderr = channel.getErrStream(); channel.connect(); waitForChannelClosed(channel); if (channel.getExitStatus() != 0) { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stderr)); readAll(bufferedReader, result); throw new Exception(result.toString()); } else { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stdout)); readAll(bufferedReader, result); } } catch (Exception e) { throw new SubprocessException(e); } finally { if (channel != null) { channel.disconnect(); } if (session != null) { session.disconnect(); } } return result.toString(); } 

@NoelYap接受的答案是错误的。

在等待命令完成时,必须连续读取输出。 否则,如果该命令产生足够的输出以填充输出缓冲区,则命令将挂起,等待缓冲区被消耗,从未发生过。 所以你陷入了僵局。

以下示例在监视命令状态的同时连续读取stdout和stderr。 它基于官方的JSch exec.java示例 (只是添加了stderr的读数)。

 ChannelExec channel = (ChannelExec)session.openChannel("exec"); channel.setCommand( "for((i=1;i<=10000;i+=2)); do echo \"Long output - $i\"; done ; " + "echo error output >&2"); InputStream commandOutput = channel.getExtInputStream(); StringBuilder outputBuffer = new StringBuilder(); StringBuilder errorBuffer = new StringBuilder(); InputStream in = channel.getInputStream(); InputStream err = channel.getExtInputStream(); channel.connect(); byte[] tmp = new byte[1024]; while (true) { while (in.available() > 0) { int i = in.read(tmp, 0, 1024); if (i < 0) break; outputBuffer.append(new String(tmp, 0, i)); } while (err.available() > 0) { int i = err.read(tmp, 0, 1024); if (i < 0) break; errorBuffer.append(new String(tmp, 0, i)); } if (channel.isClosed()) { if ((in.available() > 0) || (err.available() > 0)) continue; System.out.println("exit-status: " + channel.getExitStatus()); break; } try { Thread.sleep(1000); } catch (Exception ee) { } } System.out.println("output: " + outputBuffer.toString()); System.out.println("error: " + errorBuffer.toString()); channel.disconnect(); 

如果你while (!channel.isClosed()) {}之后添加while (!channel.isClosed()) {} channel.connect(); ,你会看到在shell for循环中有足够大的i (在我的环境中10000足够了),循环永远不会完成。