0

Normally I use this code to run a bash script and get it's output

ProcessBuilder pb = new ProcessBuilder("/home/myscript");
Process p = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
String inputRead;
p.waitFor();
while((inputRead=stdInput.readLine()) != null){
    Helper.log(inputRead);
}

This works fine but this time the bash script I am using didn't terminate. It's always active and when it detect something it print it. I want to start the script, wait for some time and than check if it detected something. I tried to use p.wait(periode); I tried this code

p.wait(10000);
while((inputRead=stdInput.readLine()) != null){
    Helper.log(inputRead);
}

I am not sure if it's the right solution for my problem but anyway I get an error with this code

java.lang.IllegalMonitorStateException

My question is not really about waiting, but how to stop the process after waiting and still be able to get the output.

Doe.J
  • 1
  • 5
  • Usually, IllegalMonitorStateException means that a thread is trying to wait/notify an object monitor without owning it. Make sure no threads are trying to do that. – jordaniac89 Oct 17 '16 at 14:23
  • I see what you're doing. p.wait() needs to be inside a synchronized statement: https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html. If you want the thread to wait, use Thread.sleep(). – jordaniac89 Oct 17 '16 at 14:25
  • The script "/home/myscript" write to a file? – Lucas Oliveira Oct 17 '16 at 14:27
  • What makes you think that calling `Object.wait()` on the `Process` object is a good idea? It's not - that method has a totally different purpose, and has the precondition that you need to hold the monitor on the object (synchronize on it). But that's not the fix for your problem. – Erwin Bolwidt Oct 17 '16 at 14:30

2 Answers2

0

Below is the complete example of the solution. A separate thread switches a flag for the main thread to terminate and then output the collected lines:

private static boolean triggerToClose = false;

  public static void main(String[] args) throws IOException,
      InterruptedException {
    ProcessBuilder pb =
        new ProcessBuilder("/home/myscript");
    Process p = pb.start();
    java.io.InputStream is = p.getInputStream();
    BufferedReader stdInput = new BufferedReader(new InputStreamReader(is));
    String inputRead;
    new Thread(new Runnable() {
      public void run() {
        try {
          Thread.sleep(10000);
        } catch (InterruptedException e) {
        }
        triggerToClose = true;
      }
    }).start();
    StringBuilder sb = new StringBuilder();
    while ((inputRead = stdInput.readLine()) != null) {
      if (triggerToClose) {
        p.destroy();
        break;
      }

      sb.append(inputRead).append('\n');
    }
    System.out.println(sb);
  }
Aram Paronikyan
  • 1,598
  • 17
  • 22
  • This might also help, http://stackoverflow.com/questions/1036754/difference-between-wait-and-sleep – Cakes Oct 17 '16 at 14:19
  • If i use this command the threat will never terminate. If i use p.destroy(); after your code I will not be able to get the output result, I got the message java.io.IOException: Stream closed – Doe.J Oct 17 '16 at 15:45
  • The sleep() command shouldn't keep the current thread running for more than the time specified as an argument. Are you sure that the process started by /home/myscript really terminates? – Aram Paronikyan Oct 17 '16 at 15:52
  • No the process /home/myscript never terminate this is the problem. I just want to run the script for a short period of time, in this example 10 seconds then stop it and get the output generated by the script in this period. – Doe.J Oct 17 '16 at 17:03
  • The answer is updated – Aram Paronikyan Oct 17 '16 at 17:39
0

In your case using .wait(1000), is totally wrong. That's what the exception also tells you.
Exactly for your usecase there's waitFor(long timeout, TimeUnit unit):

p.waitFor(10, TimeUnit.SECONDS);
Alexey Soshin
  • 16,718
  • 2
  • 31
  • 40
  • Thank you but I used your code and the threat never terminated. Maybe I should destroy the process after this code ? But as I said, if I destroy it I am not able to get the output anymore – Doe.J Oct 17 '16 at 15:46
  • Did you remove the while loop after using my proposal? – Alexey Soshin Oct 17 '16 at 15:53
  • No but the while loop is just for logging the input generated from the script. And the script never stops because I still have the input logged for ever – Doe.J Oct 17 '16 at 15:57