关于通过webapp运行ProcessBuilder的一些问题

时间:2011-10-28 11:51:01

标签: java multithreading spring thread-safety

我正在编写一个webapp,它基本上允许用户使用通过各种表单输入的参数启动shell脚本。在做了一些研究之后,我相信ProcessBuilder是运行shell脚本的最佳方式,但是我有一些条件需要我满足并且希望其他人可以告诉我,如果我正在考虑正确的行。

将启动的脚本可能需要几个小时才能运行。所以显然我不能让应用暂停并等待那么长时间。所以我想知道线程是否是这个问题的答案?我对使用线程并寻找一些建议不是很有经验。我应该在新线程中启动ProcessBuilder,以便主Web应用程序继续运行吗?这甚至会起作用吗?它只是简单地声明一个新线程并为其分配流程构建器吗?我是否必须担心运行或创建各种线程?只是不确定要注意什么或要注意哪些陷阱。

另外,我真的需要一种能够在运行过程中至少检查进程状态的方法。这些要求需要某种方式来显示流程的进度,但我不知道这是可能的。我相信能够至少表明它仍在运行应该是可以接受的。我该如何检测?

有关更多信息,它是一个Java / Spring Web应用程序,将在某些Unix上运行。感谢您的任何想法和帮助。

1 个答案:

答案 0 :(得分:3)

您可以实施类似JobManagerJob的内容。

Job可以是Runnable,其ProcessBuilder。在它的run方法中,它启动进程(ProcessBuilder.start),等待它退出并在完成时回调JobManager,可能返回进程的退出状态。

JobManager创建Jobs(每个都在新的Thread中),维护当前作业的集合(可能是最近完成的作业的集合,可能是失败作业的列表) 。客户端可以让JobManager作业执行并查询所有作业或特定作业的状态(运行,完成,失败)。

关于进程的状态,Job可以有startTime,endTime和exitStatus变量以及相关的get方法。您可以将这些返回给客户端以显示作业状态表。

您的Job.run方法可能看起来像这样。

public void run() {
  startTime = System.currentTimeMillis();  
  process = processBuilder.start();

  // spawn threads to consume process output streams
  // even if you're not going to read them

  while (running) {
    try {
      process.waitFor();
      running = false;
    } catch (InterruptedException e) {
      // you could stop a process by interrupting it's Job thread
      process.destroy();
    }
  }
  exitStatus = process.exitValue();
  endTime = System.currentTimeMillis();
  jobManager.onExit(this);
}

关于“%完成”,如果你有某种方法可以测量它,那将是唯一的。

如果某项任务应在一定时间内完成,您可以将其用作报告预计完成时间/完成百分比的粗略方式。

或许您可以捕获进程的输出,使用它在Job中设置percentComplete变量。例如,当您在输出中看到“消息X”时,请设置percentComplete = 25%。这意味着为每种类型的脚本实现自定义代码 - 可能是Job子类,或者为Job提供一个负责解析输出的成员变量。