【问题标题】:Redirecting output stream of JSch exec channel to a file using setOutputStream does not work使用 setOutputStream 将 JSch exec 通道的输出流重定向到文件不起作用
【发布时间】:2016-01-16 22:27:56
【问题描述】:

我正在使用 JSch 执行通道登录到多个服务器并运行一些命令。然后我需要捕获输出并将其存储在一个名为log 的文件中。出于某种奇怪的原因,文件在执行后保持空白。

try (OutputStream log = new BufferedOutputStream(new FileOutputStream(outputFilePath))) {
    ArrayList<String> lists = new ArrayList<String>();
    lists.add("hostname");
    lists.add("df -l");
    String host ="localhost";

    JSch jsch = new JSch();
    try {
        String user = "user";
        String password = "pass";
        Session session = jsch.getSession(user, host, 22);
        session.setPassword(password);
        session.setConfig(getProperties());
        session.setTimeout(20 * 1000);
        System.out.println(session.getTimeout());
        session.connect();
        if (session.isConnected()) {
            System.out.println(host + " Session Established ");
        }

        for (String elem : lists) {
            Channel channel = session.openChannel("exec");
            channel.setOutputStream(log);

            ((ChannelExec) channel).setCommand(elem);

            channel.setInputStream(null);

            ((ChannelExec) channel).setErrStream(System.err);

            InputStream in = channel.getInputStream();

            channel.connect();

            byte[] tmp = new byte[1024];
            while (true) {
                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()) {
                    if (in.available() > 0) {
                        continue;
                    }
                    System.out.println("exit-status: " + channel.getExitStatus());
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (Exception ee) {
                }
            }
            channel.disconnect();
        }

        session.disconnect();

程序通过 IDE 控制台显示输出,但输出文件已创建但仍为空白。

然后我将system.setOut 设置为一个文件,这会阻止控制台显示更多数据,但output.txt 文件仍为空白。

System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream("output.txt"))));

【问题讨论】:

  • 为什么不使用日志库?这可能会更容易......
  • 您有示例或链接可用作参考吗?
  • 例如:stackoverflow.com/questions/15758685/… - 但如果你用谷歌搜索“java 日志到文件示例”,我相信你会找到很多示例。

标签: java ssh jsch


【解决方案1】:

这是因为getInputStream 覆盖了setOutputStream 调用。

看看这些方法在 JSch 中是如何实现的(最终都调用了io.setOutputStream):

public void setOutputStream(OutputStream out){
  io.setOutputStream(out, false);
}

public InputStream getInputStream() throws IOException {
  int max_input_buffer_size = 32*1024;
  try {
    max_input_buffer_size =
      Integer.parseInt(getSession().getConfig("max_input_buffer_size"));
  }
  catch(Exception e){}
  PipedInputStream in =
    new MyPipedInputStream(
                           32*1024,  // this value should be customizable.
                           max_input_buffer_size
                           );
  boolean resizable = 32*1024<max_input_buffer_size;
  io.setOutputStream(new PassiveOutputStream(in, resizable), false);
  return in;
}

我假设您实际上不需要基于InputStream in 的输出读取块。只需将其删除,日志文件写入即可开始工作。


旁注:默认情况下,输出流将与通道一起关闭。当您为多个频道重复使用相同的流时,您应该防止这种情况发生。

使用dontclose 参数覆盖setOutputStream

public void setOutputStream(OutputStream out, boolean dontclose)

像这样:

channel.setOutputStream(log, true);

【讨论】:

  • 感谢您的详细解释。它真正把事情变成了前瞻性。
猜你喜欢
  • 2017-02-25
  • 2018-08-01
  • 2018-05-15
  • 2012-11-08
  • 1970-01-01
  • 2019-04-25
  • 2012-10-19
  • 1970-01-01
相关资源
最近更新 更多