使用Process.exec

时间:2010-08-12 16:16:12

标签: java processbuilder

我想在程序中间执行批处理文件(这将启动另一个java应用程序)。 我不想等待或看它是否成功执行,也不想捕获执行该批处理文件的错误。在我启动该批处理文件后,我想做其他事情,而不是在执行该批处理后等待它。

我需要照顾stdout和stderr吗? 有没有办法摆脱照顾stdout和stderr。

这是我的第二篇文章,以清除我对这个主题的困惑,所以请具体问题,不要扔掉 有关如何处理脚本或进程构建器的链接。

感谢任何帮助。

4 个答案:

答案 0 :(得分:3)

简答:否。根据流程'javadocs

  

由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此无法及时写入输入流或读取子进程的输出流可能导致子进程阻塞,甚至死锁。

因此,如果您希望程序具有远程可靠性,则必须处理stderr和stdout处理。

话虽如此,如果你真的不关心他们的内容(这是一个坏主意 - 如果批量失败并带有你丢弃的有用错误消息怎么办?),你可以根据{{​​3}}触发线程来读取它们。这将使您的逻辑线程继续而不用担心流的状态,并且流食者将在后台运行直到流耗尽。你可能甚至想要创建一个围绕Runtime.exec()的包装器来触发线程为你做这件事,如果你发现自己这么做了。

但是,如果您不打算在代码中解释它,我至少会记录批处理过程的输出。当批次出现问题时,通过流程的输出来分析问题会更加容易。

答案 1 :(得分:2)

我发现如果你至少不吃stdout和stderr,你最终会耗尽内存。这也阻止我同时运行多个Process

我一直在使用一个名为ProcessStreamEater的类来执行此操作。

public class ProcessStreamEater implements Runnable
{
   private final Process proc;

   public ProcessStreamEater(Process proc)
   {
      this.proc = proc;
   }

   @Override
   public void run()
   {
      InputStreamReader r = new InputStreamReader(proc.getInputStream());
      try
      {
         while(r.read() != -1)
         {  // put stuff here if you want to do something with output
            // otherwise, empty
         }
      }
      catch(IOException e)
      {
         // handle IO exception
      }
      finally
      {
         if(r != null)
         {
            try
            {
               r.close();
            }
            catch(IOException c)
            {}
         }
      }
   }
}

然后我用它来吃东西......

   ProcessBuilder pb = new ProcessBuilder(args);
   pb.redirectErrorStream(true);
   final Process proc = pb.start();
   executorService.execute(new ProcessStreamEater(proc));

其中executorService是使用Executors.newCachedThreadPool()

创建的

答案 2 :(得分:0)

我认为你只需要这个:

Runtime run = Runtime.getRuntime();  
Process p = null;  
String cmd = "D:\\a.bat";     
try {     
  p = run.exec(cmd);
}catch(Exception e){
  //do handling
}

//你的代码

请记住稍后在代码中调用p.destroy()。 您还可以在单​​独的线程中生成上面的代码。 希望这会有所帮助。

答案 3 :(得分:0)

如果你的进程没有向stdout或stderror产生任何输出,那么你可能不需要处理它。如果您的子进程确实产生了输出,那么可能在尝试写入stdout时永远阻塞,这取决于OS管道缓冲区的数量。这里有一个关于流冲洗器的例子 - 每个人都使用它。