Skip to content

Commit a3d729d

Browse files
committed
fix[command]: process destroy gracefully
1 parent 7e609a2 commit a3d729d

1 file changed

Lines changed: 57 additions & 38 deletions

File tree

monitor/src/main/java/com/zfoo/monitor/util/OSUtils.java

Lines changed: 57 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616
import com.zfoo.monitor.*;
1717
import com.zfoo.net.util.NetUtils;
1818
import com.zfoo.protocol.exception.RunException;
19-
import com.zfoo.protocol.util.FileUtils;
20-
import com.zfoo.protocol.util.IOUtils;
21-
import com.zfoo.protocol.util.StringUtils;
22-
import com.zfoo.protocol.util.UuidUtils;
19+
import com.zfoo.protocol.util.*;
2320
import com.zfoo.scheduler.util.TimeUtils;
2421
import org.slf4j.Logger;
2522
import org.slf4j.LoggerFactory;
@@ -29,6 +26,7 @@
2926
import oshi.software.os.OperatingSystem;
3027

3128
import java.io.File;
29+
import java.io.IOException;
3230
import java.io.InputStream;
3331
import java.text.NumberFormat;
3432
import java.util.ArrayList;
@@ -258,54 +256,75 @@ public static SystemInfo os() {
258256
// -----------------------------------------------------------------------------------------------------------------
259257
public static String execCommand(String command) {
260258
logger.info("execCommand [{}]", command);
261-
return doExecCommand(command, null);
259+
try {
260+
return doExecCommand(command, null);
261+
} catch (IOException | InterruptedException e) {
262+
throw new RuntimeException(e);
263+
}
262264
}
263265

264266

265267
public static String execCommand(String command, String workingDirectory) {
266268
logger.info("execCommand [{}] workingDirectory:[{}]", command, workingDirectory);
267269
FileUtils.createDirectory(workingDirectory);
268270
var wd = new File(workingDirectory);
269-
return doExecCommand(command, wd);
271+
try {
272+
return doExecCommand(command, wd);
273+
} catch (IOException | InterruptedException e) {
274+
throw new RuntimeException(e);
275+
}
270276
}
271277

272-
public static String doExecCommand(String command, File wd) {
273-
Process process = null;
274-
InputStream inputStream = null;
275-
try {
276-
var commandSplits = command.split(StringUtils.SPACE_REGEX);
277-
process = new ProcessBuilder(commandSplits)
278-
.redirectErrorStream(true)
279-
.directory(wd)
280-
.start();
281-
282-
var finished = process.waitFor(256, TimeUnit.SECONDS);
283-
if (!finished) {
284-
process.destroyForcibly();
285-
throw new RunException("doExecCommand timeout with process of command:[{}]", command);
278+
private static String doExecCommand(String command, File wd) throws IOException, InterruptedException {
279+
var commandSplits = command.split(StringUtils.SPACE_REGEX);
280+
var process = new ProcessBuilder(commandSplits)
281+
.redirectErrorStream(true)
282+
.directory(wd)
283+
.start();
284+
285+
var out = new StringBuilder();
286+
var err = new StringBuilder();
287+
288+
// 异步读取输出,避免缓冲区阻塞
289+
var outThread = new Thread(ThreadUtils.safeRunnable(() -> {
290+
try {
291+
out.append(StringUtils.bytesToString(IOUtils.toByteArray(process.getInputStream())));
292+
} catch (IOException e) {
293+
throw new RuntimeException(e);
294+
}
295+
}));
296+
var errThread = new Thread(() -> {
297+
try {
298+
err.append(StringUtils.bytesToString(IOUtils.toByteArray(process.getErrorStream())));
299+
} catch (IOException e) {
300+
throw new RuntimeException(e);
286301
}
302+
});
287303

288-
//取得命令结果的输出流
289-
inputStream = process.getInputStream();
290-
var bytes = IOUtils.toByteArray(inputStream);
291-
var result = StringUtils.bytesToString(bytes);
304+
outThread.start();
305+
errThread.start();
292306

293-
// 获取线程的退出值,0代表正常退出,非0代表异常中止
294-
int exitValue = process.exitValue();
295-
if (exitValue != 0) {
296-
throw new RunException("doExecCommand error executing command exitValue:[{}] result:[{}]", exitValue, result);
297-
}
307+
var finished = process.waitFor(256, TimeUnit.SECONDS);
308+
if (!finished) {
309+
process.destroyForcibly();
310+
logger.error("doExecCommand timeout with process of command:[{}]", command);
311+
}
298312

299-
return result;
300-
} catch (Exception e) {
301-
logger.error("doExecCommand unknown exception in command execution", e);
302-
} finally {
303-
if (process != null) {
304-
process.destroy();
305-
}
306-
IOUtils.closeIO(inputStream);
313+
process.destroy();
314+
315+
outThread.join();
316+
errThread.join();
317+
318+
// 获取线程的退出值,0代表正常退出,非0代表异常中止
319+
int exitValue = process.exitValue();
320+
if (exitValue != 0) {
321+
logger.error("doExecCommand error executing command exitValue:[{}] result:[{}] err:[{}]", exitValue, err, err);
322+
}
323+
324+
if (!err.isEmpty()) {
325+
logger.error("doExecCommand error executing command err:[{}]", err);
307326
}
308327

309-
return StringUtils.EMPTY;
328+
return out.toString();
310329
}
311330
}

0 commit comments

Comments
 (0)