我正在编写一个webapp,它基本上允许用户使用通过各种表单输入的参数启动shell脚本。在做了一些研究之后,我相信ProcessBuilder是运行shell脚本的最佳方式,但是我有一些条件需要我满足并且希望其他人可以告诉我,如果我正在考虑正确的行。
将启动的脚本可能需要几个小时才能运行。所以显然我不能让应用暂停并等待那么长时间。所以我想知道线程是否是这个问题的答案?我对使用线程并寻找一些建议不是很有经验。我应该在新线程中启动ProcessBuilder,以便主Web应用程序继续运行吗?这甚至会起作用吗?它只是简单地声明一个新线程并为其分配流程构建器吗?我是否必须担心运行或创建各种线程?只是不确定要注意什么或要注意哪些陷阱。
另外,我真的需要一种能够在运行过程中至少检查进程状态的方法。这些要求需要某种方式来显示流程的进度,但我不知道这是可能的。我相信能够至少表明它仍在运行应该是可以接受的。我该如何检测?
有关更多信息,它是一个Java / Spring Web应用程序,将在某些Unix上运行。感谢您的任何想法和帮助。
答案 0 :(得分:3)
您可以实施类似JobManager
和Job
的内容。
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提供一个负责解析输出的成员变量。