如何读取 JSch 命令输出? [英] How to read JSch command output?

查看:42
本文介绍了如何读取 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];
}

它正在挂起试图从读者那里阅读.我该如何解决?我该如何追查正在发生的事情?

It's hanging trying to read from the reader. How do I fix this? How do I go about hunting down what's happening?

推荐答案

必须连续读取输出,同时等待命令完成.否则,如果该命令产生足够的输出来填充输出缓冲区,则该命令将挂起,等待缓冲区被消耗,这将永远不会发生.所以你会陷入僵局.

One has to read the output continuously, while waiting for the command to finish. Otherwise, if the command produces enough output to fill in an output buffer, the command will hang, waiting for the buffer to be consumed, what never happens. So you get a deadlock.

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

The following example reads both stdout and stderr continuously, while monitoring a command status. It is based on the official JSch exec.java example (just adds a reading of 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");

ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream();

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.write(tmp, 0, i);
    }
    while (err.available() > 0) {
        int i = err.read(tmp, 0, 1024);
        if (i < 0) break;
        errorBuffer.write(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("UTF-8"));
System.out.println("error: " + errorBuffer.toString("UTF-8"));

channel.disconnect();


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


If you add while (!channel.isClosed()) {} after the channel.connect();, you will see that with a sufficiently large i in the shell for loop (10000 is enough with in my environment), the loop never finishes.

这篇关于如何读取 JSch 命令输出?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆