Получить вывод работающего сценария bash с помощью java

Обычно я использую этот код для запуска сценария bash и получения его вывода

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

Это работает нормально, но на этот раз сценарий bash, который я использую, не завершился. Он всегда активен и при обнаружении чего-либо распечатывает это. Я хочу запустить скрипт, подождать некоторое время, а затем проверить, обнаружил ли он что-нибудь. Я пробовал использовать p.wait(periode); Я пробовал этот код

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

Я не уверен, что это правильное решение моей проблемы, но в любом случае я получаю сообщение об ошибке с этим кодом

java.lang.IllegalMonitorStateException

На самом деле мой вопрос не в ожидании, а в том, как остановить процесс после ожидания и при этом получить результат.


person Doe.J    schedule 17.10.2016    source источник
comment
Обычно IllegalMonitorStateException означает, что поток пытается дождаться / уведомить объектный монитор, не владея им. Убедитесь, что ни один поток не пытается это сделать.   -  person jordaniac89    schedule 17.10.2016
comment
Я вижу, что ты делаешь. p.wait () должен находиться внутри синхронизированного оператора: docs.oracle .com / javase / tutorial / essential / concurrency /. Если вы хотите, чтобы поток ждал, используйте Thread.sleep ().   -  person jordaniac89    schedule 17.10.2016
comment
Скрипт / home / myscript пишет в файл?   -  person Lucas Oliveira    schedule 17.10.2016
comment
Что заставляет вас думать, что вызов Object.wait() объекта Process - хорошая идея? Это не так - этот метод имеет совершенно другое назначение и имеет предварительное условие, что вам нужно удерживать монитор на объекте (синхронизировать по нему). Но это не решение вашей проблемы.   -  person Erwin Bolwidt    schedule 17.10.2016


Ответы (2)


В вашем случае использование .wait (1000) совершенно неверно. Об этом также сообщает исключение.
Именно для вашего варианта использования существует waitFor(long timeout, TimeUnit unit):

p.waitFor(10, TimeUnit.SECONDS);
person Alexey Soshin    schedule 17.10.2016
comment
Спасибо, но я использовал ваш код, и угроза так и не исчезла. Может, стоит после этого кода уничтожить процесс? Но, как я уже сказал, если я его уничтожу, я больше не смогу получить результат - person Doe.J; 17.10.2016
comment
Вы удалили цикл while после использования моего предложения? - person Alexey Soshin; 17.10.2016
comment
Нет, но цикл while предназначен только для регистрации ввода, сгенерированного сценарием. И сценарий никогда не останавливается, потому что у меня все еще есть входные данные навсегда - person Doe.J; 17.10.2016

Ниже приведен полный пример решения. Отдельный поток устанавливает флаг для завершения основного потока, а затем выводит собранные строки:

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);
  }
person Aram Paronikyan    schedule 17.10.2016
comment
Это также может помочь, stackoverflow.com/questions/1036754/ - person Cakes; 17.10.2016
comment
Если я использую эту команду, угроза никогда не исчезнет. Если я использую p.destroy (); после вашего кода я не смогу получить результат вывода, я получил сообщение java.io.IOException: Stream closed - person Doe.J; 17.10.2016
comment
Команда sleep () не должна заставлять текущий поток работать дольше времени, указанного в качестве аргумента. Вы уверены, что процесс, запущенный / home / myscript, действительно завершается? - person Aram Paronikyan; 17.10.2016
comment
Нет, процесс / home / myscript никогда не завершается, это проблема. Я просто хочу запустить сценарий на короткий период времени, в этом примере 10 секунд, затем остановить его и получить результат, сгенерированный сценарием за этот период. - person Doe.J; 17.10.2016
comment
Ответ обновлен - person Aram Paronikyan; 17.10.2016