【问题标题】:Get output of a running bash script with java [duplicate]使用java获取正在运行的bash脚本的输出[重复]
【发布时间】:2017-02-26 13:46:13
【问题描述】:

通常我使用这段代码来运行一个 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

我的问题实际上不是关于等待,而是如何在等待后停止进程并且仍然能够获得输出。

【问题讨论】:

  • 通常,IllegalMonitorStateException 意味着线程试图等待/通知对象监视器而不拥有它。确保没有线程试图这样做。
  • 我明白你在做什么。 p.wait() 需要在同步语句中:docs.oracle.com/javase/tutorial/essential/concurrency/…。如果您希望线程等待,请使用 Thread.sleep()。
  • 脚本“/home/myscript”写入文件?
  • 是什么让您认为在Process 对象上调用Object.wait() 是个好主意?不是-该方法具有完全不同的目的,并且具有您需要将监视器保持在对象上的前提条件(对其进行同步)。但这不能解决您的问题。

标签: java processbuilder


【解决方案1】:

在您的情况下使用 .wait(1000) 是完全错误的。这也是异常告诉你的。
waitFor(long timeout, TimeUnit unit):

正好适合您的用例
p.waitFor(10, TimeUnit.SECONDS);

【讨论】:

  • 谢谢,但我使用了您的代码,威胁从未终止。也许我应该在这段代码之后销毁这个过程?但正如我所说,如果我将其销毁,我将无法再获得输出
  • 您在使用我的建议后是否删除了 while 循环?
  • 否,但 while 循环仅用于记录脚本生成的输入。而且脚本永远不会停止,因为我仍然永远记录输入
【解决方案2】:

以下是解决方案的完整示例。一个单独的线程切换一个标志,让主线程终止,然后输出收集到的行:

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

【讨论】:

  • 这可能也有帮助,stackoverflow.com/questions/1036754/…
  • 如果我使用这个命令,威胁将永远不会终止。如果我使用 p.destroy();在您的代码之后我将无法获得输出结果,我收到消息 java.io.IOException: Stream closed
  • sleep() 命令不应使当前线程运行超过作为参数指定的时间。你确定 /home/myscript 启动的进程真的终止了吗?
  • 没有进程 /home/myscript 永远不会终止这是问题所在。我只想运行脚本一小段时间,在本例中为 10 秒,然后停止它并获取脚本在此期间生成的输出。
  • 答案已更新
猜你喜欢
  • 2021-07-13
  • 2022-11-25
  • 2014-12-18
  • 1970-01-01
  • 2019-02-08
  • 1970-01-01
  • 2014-01-18
  • 1970-01-01
  • 2019-06-24
相关资源
最近更新 更多