关于Spring Batch 执行系统命令时进程阻塞的问题
2013-05-21 00:00
369 查看
Spring Batch提供了SystemCommandTasklet用来执行系统命令。底层使用JDK Runtime.exec()方法,Process.waitFor()来获取运行结果。
SystemCommandTasklet部分源码:
SystemCommandTasklet没处理系统命令的输入输出。当输出大于系统限制缓冲区大小时,就会阻塞得不到返回。
例如我测试的在32位Windows下当输入超过512个字母时,进程被卡住不會结束。
修改使其处理执行系统命令时的输出(不太可能有输入所以没处理):
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();
相关文章推荐
- 关于C#远程执行命令后,在远程主机上能看到进程但看不到交互窗口的问题(一)
- c#关闭系统进程以及如何调用cmd并执行命令
- JAVA调用系统命令或可执行程序--返回一个Runtime运行时对象,然后启动另外一个进程来执行命令
- 关于病毒模块插入系统、应用程序进程的问题
- java执行bat命令碰到的阻塞问题
- 关于系统进程lsass.exe的病毒问题
- 关于VS220113无法启动IIS Express,系统日志:工作进程未能预加载 .Net 运行时版本 v4.0.30128问题
- linux的一些基本命令(关于文件操作, 进程操作,以及/boot问题)
- 问题汇总-20130927-关于rc.local命令无法执行
- 关于在sqlplus命令环境中执行ed命令的问题
- VMware 虚拟机 Ubuntu 系统执行 ifconfig 命令 eth0没有IP地址(intet addr、Bcast、Mask) 解决:UP BROADCAST MULTICAST 问题
- Java外部执行操作系统命令(Java 创建本地系统进程)
- 问题:子进程父进程哪个先执行:【转】关于 fork 和父子进程的理解
- 关于查看进程、系统、用户、内核、及一些硬件设备的命令
- c#关闭系统进程以及如何调用cmd并执行命令
- 线程系统调用阻塞是否导致进程阻塞的问题
- 关于"试图执行系统不支持的操作"问题
- 关于hibernate执行sql语句后,进程不关闭的问题
- java执行bat命令碰到的阻塞问题的解决方法
- 关闭系统进程,以及如何调用cmd并执行命令