【问题标题】:Redirect a system call output to a file with Java使用 Java 将系统调用输出重定向到文件
【发布时间】:2012-06-05 09:15:48
【问题描述】:

目前无法将小型 Windows 批处理控制台的输出重定向到日志文件。我的 Java 应用程序需要启动 Runtime.exec() 调用而不等待它完成并仍然记录输出。这是我的记录器类:

public class BatchThreadLogger extends Thread {
  private Process process;
  private String logFilePath;
  private static final Logger logger = Logger.getLogger(BatchThreadLogger.class);

  public BatchThreadLogger(Process process, String logFilePath) {
    this.process = process;
    this.logFilePath = logFilePath;
  }

  public void run() {
    try {
      // create logging file
      File file = new File(logFilePath);
      file.createNewFile();

      // create a writer object
      OutputStream os = new FileOutputStream(file);
      PrintWriter pw = new PrintWriter(os);

      // catch the process output in an InputStream
      InputStreamReader isr = new InputStreamReader(process.getInputStream());
      BufferedReader br = new BufferedReader(isr);

      // wait for the process to complete
      int processStatus = process.waitFor();

      // redirect the output to the log file
      String line = null;
      while ((line = br.readLine()) != null) {
        pw.println(line);
      }

      // add a small message with the return code to the log
      pw.println("********************************************");
      pw.println("********************************************");
      pw.println("Batch call completed with return status " + processStatus);

      pw.flush();
      os.close();
    }
    catch (IOException e) {
      logger.error("IOException raised during batch logging on file " + logFilePath, e);
    }
    catch (InterruptedException e) {
      logger.error("InterruptedException raised during batch process execution", e);
    }
  }
}

我的电话很简单:

Process process = Runtime.getRuntime().exec(command);
BatchThreadLogger logger = new BatchThreadLogger(process, logFilePath);
logger.start();

我的命令目前只是用两个参数调用我的 test.bat。我的测试批次现在就可以了:

echo "BATCH CALLED WITH PARAMETER %1 AND %2"
exit

我的日志文件只包含:

********************************************
********************************************
Batch call completed with return status 0

我尝试在将输出重定向到日志文件的代码之前和之后放置waitFor()call,但没有成功。我总是看到正在启动的命令的黑屏,但日志中没有任何内容...

任何帮助将不胜感激,我遗漏了一些东西,但不明白是什么......

【问题讨论】:

    标签: java multithreading logging file-io iostream


    【解决方案1】:

    您没有从您创建的流程的标准错误中读取数据。

    我怀疑一条错误消息正在写入标准错误,并且因为您只是从标准输出中读取,所以您没有收到此错误。

    我建议您使用 ProcessBuilder 替换您对 Runtime.getRuntime().exec(...) 的使用,使用类似以下内容:

    ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "test.bat", "One", "Two");
    pb.redirectErrorStream(true);
    Process process = pb.start();
    

    pb.redirectErrorStream(true); 行将进程的标准错误重定向到其标准输出,因此您不必在两个单独的线程中从两个流(标准输出和标准错误)中读取。

    【讨论】:

    • 我不确定你的回答。我想知道如何在批处理文件中回显文本可以被视为错误并因此被定向到流程执行的错误流。可以肯定的是,我用getErrorStream() 替换了getInputStream() 调用,但它仍然不起作用......日志文件中没有任何内容......
    • 我还在 echo 调用之后添加了一个随机的ping www.google.ch,只是为了确保 echo 输出不会重定向到特殊的流或任何类似的技巧......日志中仍然没有任何内容。顺便说一句,我发布的代码确实适用于 Linux。关于您的 ProcessBuilder 提议,我会看看它是否可以轻松替换 Runtime.exec() 调用。
    • 我想您在尝试运行不存在或由于权限问题而无法读取的批处理文件时可能会出错。不过,奇怪的是没有输出。您介意分享您的command 变量中的确切内容吗?这部分属于哪种应用程序(例如命令行、Web 应用程序、GUI、服务)?
    • 当然,命令是cmd /c start C:/ieu/test.bat spjc010j SPJ5000006000010101010。这是从在 SessionBean 中运行在 JBoss 7 下的 Web 应用程序开始的。
    • 您使用start 有什么原因吗?你试过在没有start 的情况下运行你的命令吗? start 在单独的命令提示符窗口中运行程序,而您使用 start 运行的程序的输出将转到这个新窗口,而不是您的 process
    猜你喜欢
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 2016-06-23
    相关资源
    最近更新 更多