2009-06-24 84 views
2

有没有办法在Java中定期运行Unix命令(在我的情况下是ps)?我写的循环:在Java中重复Unix命令

while(this.check) 
{ 
    try 
    { 
      ProcessBuilder pb = new ProcessBuilder("ps"); 
      Process proc; 

      System.out.println(" * * Running `ps` * * "); 

      byte[] buffer; 
      String input; 

      proc = pb.start(); 
      BufferedInputStream osInput = 
       new BufferedInputStream(proc.getInputStream()); 

      //prints 0 every time after the first 
      System.out.println(osInput.available()); 

      buffer = new byte[osInput.available()]; 
      osInput.read(buffer); 
      input = new String(buffer); 
      for(String line : input.split("\n")) 
      { 
       if(line.equals("")) 
        continue; 
       this.handlePS(line); 
      } 

      proc.destroy(); 
      try 
      { 
       Thread.sleep(10000); 
      } 
      catch (InterruptedException ie) 
      { 
       ie.printStackTrace(); 
      } 
     } 
     catch (IOException ioe) 
     { 
      ioe.printStackTrace(); 
     } 
    } 
} 

不起作用。它第一次运行得非常好,但每次输入流中都有0个字节可用。我试试watch命令,但是这个Solaris盒没有这个命令。我不能使用cron作业,因为我需要知道PID是否存在于Java应用程序中。有任何想法吗?

在此先感谢。

编辑:不能使用cron作业

编辑:我正在做同一类型(PS)的新Thread它结束后,所以我每次都无疑使新的ProcessBuilder。

编辑:我把环没有工作回来,因为它造成混乱。

+0

我没有看到一个循环。 – 2009-06-24 19:00:17

+0

把环路放回来避免任何混淆 – geowa4 2009-06-24 19:29:56

回答

3

我不确定循环的位置,但是您需要在循环中每次创建一个新的对象(并因此创建一个新的InputStream)。否则,你会一直在看第一个电话的结果。 ProcessBuilder的javadoc表明您不需要每次创建其中一个。

当您拨打电话available()时,可能还存在输入流尚未准备好的争用情况。在打印结果之前,你应该考虑确保输入流已经达到了EOF(这将在ps中发生,尽管不是顶部)。

虽然我不知道“ps”的输出是什么样的编码(ASCII以外),但您也没有正确处理编码。由于“ps”可能是ASCII,所以这是相当安全的,但可能不适用于其他命令(以及其他输入流)。

+0

是的,我每做一个新的过程。你读过代码吗? – geowa4 2009-06-24 19:20:12

1

除了Kathy的回答,您还应该在每个调用的单独线程中收集stdout和stderr。否则,该进程将阻止您等待您读取此数据。

有关更多详细信息,请参阅this answer

编辑。你打电话waitFor()收集任何退出状态?我通常会这样做的方式是执行,然后拨打waitFor()。我认为destroy()在这种情况下可能是多余的。

1

所以我认为问题是你在ps执行结束之前检查输入流。尝试添加:调用osInput.available前

proc.waitFor()

()。

这里是我会如何实现它:

TimerTask task = new TimerTask() { 

     private void work() throws Exception { 
      System.out.println("Now"); 
      ProcessBuilder pb = new ProcessBuilder("ps"); 
      Process p = pb.start(); 
      p.waitFor(); 
      BufferedReader reader 
       = new BufferedReader(new InputStreamReader(p.getInputStream())); 
      String line; 
      while ((line = reader.readLine()) != null) { 
       // Process line 
       System.out.println(line); 
      } 
     } 

     @Override 
     public void run() { 
      try { 
       work(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 

    Timer timer = new Timer(); 
    long period = 5000; 
    timer.scheduleAtFixedRate(task, 0, period);