您的位置:首页 > 编程语言 > Java开发

关于Spring Batch 执行系统命令时进程阻塞的问题

2013-05-21 00:00 369 查看
Spring Batch提供了SystemCommandTasklet用来执行系统命令。底层使用JDK Runtime.exec()方法,Process.waitFor()来获取运行结果。

SystemCommandTasklet部分源码:

public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

FutureTask<Integer> systemCommandTask = new FutureTask<Integer>(new Callable<Integer>() {

@Override
public Integer call() throws Exception {
Process process = Runtime.getRuntime().exec(command, environmentParams, workingDirectory);

return process.waitFor();
}

});

long t0 = System.currentTimeMillis();

taskExecutor.execute(systemCommandTask);

while (true) {
Thread.sleep(checkInterval);
if (systemCommandTask.isDone()) {
contribution.setExitStatus(systemProcessExitCodeMapper.getExitStatus(systemCommandTask.get()));
return RepeatStatus.FINISHED;
}
else if (System.currentTimeMillis() - t0 > timeout) {
systemCommandTask.cancel(interruptOnCancel);
throw new SystemCommandException("Execution of system command did not finish within the timeout");
}
else if (execution.isTerminateOnly()) {
systemCommandTask.cancel(interruptOnCancel);
throw new JobInterruptedException("Job interrupted while executing system command '" + command + "'");
}
}

}
Process 的Javadoc写到:

The parent process uses these streams to feed input to and get output
from the subprocess.  Because some native platforms only provide
limited buffer size for standard input and output streams, failure
to promptly write the input stream or read the output stream of
the subprocess may cause the subprocess to block, or even deadlock.


SystemCommandTasklet没处理系统命令的输入输出。当输出大于系统限制缓冲区大小时,就会阻塞得不到返回。

例如我测试的在32位Windows下当输入超过512个字母时,进程被卡住不會结束。

修改使其处理执行系统命令时的输出(不太可能有输入所以没处理):

Process process = Runtime.getRuntime().exec(command, environmentParams, workingDirectory);
final InputStream inputStream = process.getInputStream();
final InputStream errorStream = process.getErrorStream();
Runnable r1 = new Runnable() {

public void run() {
BufferedReader br = null;
try {
if (logger.isInfoEnabled()) {
br = new BufferedReader(new InputStreamReader(inputStream));
for (String read = br.readLine(); read != null; read = br.readLine()) {
logger.info("Command out - " + read);
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e1) {
// ignore
}
}
}
};
Runnable r2 = new Runnable() {

public void run() {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(errorStream));
for (String read = br.readLine(); read != null; read = br.readLine()) {
logger.error("Command error - " + read);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
try {
if (br != null) {
br.close();
}
} catch (IOException e1) {
// ignore
}
}
}
};
r1.run();
r2.run();
return process.waitFor();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息