使用setOutputStream将JSch exec通道的输出流重定向到文件不起作用

时间:2016-01-16 22:27:56

标签: java ssh jsch

我正在使用JSch exec频道登录多个服务器并运行一些命令。然后我需要捕获输出并将其存储在名为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"))));

1 个答案:

答案 0 :(得分:2)

这是因为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的输出读取块。只需删除它,日志文件写入应该开始工作。

旁注:默认情况下,输出流将与频道关闭。当您为多个频道重复使用相同的流时,您应该阻止它。

使用setOutputStream覆盖dontclose参数:

public void setOutputStream(OutputStream out, boolean dontclose)
像这样:

channel.setOutputStream(log, true);