简介
Java调用Shell命令运行子进程的方式如下代码:1
2
3
4
5
6ProcessBuilder processBuilder = new ProcessBuilder("pwd");
Process process = processBuilder.start();
if (process.waitFor(timeout, TimeUnit.MILLISECONDS)) {
status = process.exitValue();
System.out.println(status);
}
现在需要在子进程运行过程中,实时收集子进程输出流的行输出,因此需要设计算法实现该功能。
设计
采用监听模式,调用子进程执行Shell命令同时注册监听器
子进程行输出将以实时调用监听器对象传参的方式传递给监听器。
原始程序流程图:
核心代码片段
1 | public static int execute(String command, String directory, Long timeout, final Communicator... communicators) throws CommandTimeoutException { |
说明:
方法参数 | 说明 |
---|---|
command | Shell命令 |
directory | 执行命令的目录路径 |
timeout | 命令执行等待时间,null则一直等待直到命令执行结束 |
communicators | 交互对象列表,子进程运行输出监听器 |
用法示例
用法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void simpleTest() {
try {
int exitValue = ShellExecutor.execute(
"./test.sh",
System.getProperty("user.dir")+"/scripts",
null,
(message, process) -> System.out.println(message)
);
System.out.println("exitValue: " + exitValue);
} catch (ShellExecutor.CommandTimeoutException e) {
System.out.println(e.getMessage());
}
}
Shell脚本 test.sh 如下:1
2
3
4
5
6
7
8
9
10
11
12
13#!/bin/bash
source /etc/profile
i=0
while((${i} < 20))
do
echo "Printout success, index: ${i}"
let "i++"
sleep 2
done
exit 0
结果输出1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21Printout success, index: 0
Printout success, index: 1
Printout success, index: 2
Printout success, index: 3
Printout success, index: 4
Printout success, index: 5
Printout success, index: 6
Printout success, index: 7
Printout success, index: 8
Printout success, index: 9
Printout success, index: 10
Printout success, index: 11
Printout success, index: 12
Printout success, index: 13
Printout success, index: 14
Printout success, index: 15
Printout success, index: 16
Printout success, index: 17
Printout success, index: 18
Printout success, index: 19
exitValue: 0