2009-06-24 17 views
2

Gibt es eine Möglichkeit, in Java regelmäßig einen Unix-Befehl (ps in meinem Fall) auszuführen? Die Schleife, die ich schrieb:Unix-Befehl in Java wiederholen

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(); 
     } 
    } 
} 

funktioniert nicht. Es läuft beim ersten Mal einwandfrei, aber es sind immer noch 0 Bytes aus dem Eingabestrom verfügbar. Ich würde versuchen, den watch Befehl, aber diese Solaris-Box hat das nicht. Ich kann keinen Cron-Job verwenden, da ich wissen muss, ob die PID in der Java-Anwendung vorhanden ist. Irgendwelche Ideen?

Vielen Dank im Voraus.

EDIT: kann nicht Cron-Job

EDIT: Ich bin eine neue Thread des gleichen Typs zu machen (PS) nach dem Schluss gelangt, so dass ich auf jeden Fall eine neue Process jedes Mal machen.

EDIT: Ich legte die Schleife, die nicht funktioniert wieder da es Verwirrung verursacht.

+0

Ich sehe keine Schleife. –

+0

Setzen Sie die Schleife zurück, um Verwirrung zu vermeiden – geowa4

Antwort

3

Ich bin mir nicht sicher, wo die Schleife ist, aber Sie müssen jedes Mal ein neues Proc Objekt (und damit ein neues InputStream) durch die Schleife erstellen. Sonst sehen Sie immer das Ergebnis beim ersten Anruf. Die Javadocs für ProcessBuilder zeigen an, dass Sie nicht jedes Mal eines erstellen müssen.

Es kann auch eine Racebedingung geben, bei der der Eingangsstrom noch nicht bereit ist, wenn Sie available() anrufen. Sie sollten sicherstellen, dass der Eingabestream EOF erreicht hat (was bei ps passieren wird, jedoch nicht mit, sagen wir, oben), bevor die Ergebnisse gedruckt werden.

Sie sind auch nicht richtig Codierung, obwohl ich nicht weiß, welche Art der Codierung die Ausgabe von "PS" ist (außerhalb von ASCII). Da "ps" wahrscheinlich ASCII ist, ist dies einigermaßen sicher, aber möglicherweise nicht für andere Befehle (und für andere Eingabeströme).

+0

Ja, ich mache jedes Mal einen neuen Prozess. Hast du den Code gelesen? – geowa4

+0

setzen Sie die Schleife, die nicht funktioniert zurück, um Verwirrung zu vermeiden – geowa4

+0

Der Code hatte keine klare Schleife (vor der Bearbeitung), da es nicht klar war, was die Methodengrenzen waren –

1

Zusätzlich zu Kathys Antwort sollten Sie auch stdout und stderr in separaten Threads für jeden Aufruf sammeln. Andernfalls blockiert der Prozess das Warten auf das Lesen dieser Daten.

Weitere Informationen finden Sie unter this answer.

BEARBEITEN. Rufen Sie waitFor() an, um einen Exit-Status zu erhalten? Die Art, wie ich mich normalerweise nähern würde, ist auszuführen und dann waitFor() aufzurufen. Ich denke, destroy() kann in diesem Zusammenhang redundant sein.

+0

haben es geschafft. Danke für den Tipp! Ich rief waitFor() gleich nach dem Start des Prozesses an – geowa4

1

Also ich denke, dass das Problem ist, dass Sie den Eingabestream vor dem Ende der PS-Ausführung überprüfen. Versuchen Sie:

proc.waitFor()

vor osInput.available() aufrufen.

Hier ist, wie ich es umgesetzt haben würde:

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);