Java创建子进程(Process)执行外部命令底层的方法是new ProcessBuilder().start()或Runtime.getRuntime().exec()。
Apache commons-exec对底层进行封装,提供了更加详细的设置和监控方法。
pom.xml
1 2 3 4 5
| <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-exec</artifactId> <version>1.3</version> </dependency>
|
CmdHelper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| import java.io.IOException; import java.io.OutputStream; import java.util.concurrent.CompletableFuture;
import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DefaultExecutor; import org.apache.commons.exec.ExecuteWatchdog; import org.apache.commons.exec.PumpStreamHandler; import org.apache.commons.exec.ShutdownHookProcessDestroyer;
public class CmdHelper {
public static CmdHandler run(CommandLine commandLine, OutputStream out, long timeout) { PumpStreamHandler pumpStreamHandler = null; if (null == out) { pumpStreamHandler = new PumpStreamHandler(); } else { pumpStreamHandler = new PumpStreamHandler(out); }
DefaultExecutor executor = new DefaultExecutor(); CmdHandler cmdHandler = new CmdHandler(executor); executor.setStreamHandler(pumpStreamHandler); ShutdownHookProcessDestroyer processDestroyer = new ShutdownHookProcessDestroyer(); executor.setProcessDestroyer(processDestroyer);
if (timeout <= 0) { timeout = ExecuteWatchdog.INFINITE_TIMEOUT; } ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout); executor.setWatchdog(watchdog);
try { executor.execute(commandLine, cmdHandler); cmdHandler.waitFor(); } catch (IOException | InterruptedException e) { e.printStackTrace(); } return cmdHandler; }
public static CompletableFuture<CmdHandler> exec(CommandLine commandLine, OutputStream out, long timeout) { CompletableFuture<CmdHandler> cf = new CompletableFuture<>(); PumpStreamHandler pumpStreamHandler = null; if (null == out) { pumpStreamHandler = new PumpStreamHandler(); } else { pumpStreamHandler = new PumpStreamHandler(out); }
DefaultExecutor executor = new DefaultExecutor(); CmdHandler cmdHandler = new CmdHandler(executor); cmdHandler.setCallback(() -> { cf.complete(cmdHandler); }); executor.setStreamHandler(pumpStreamHandler); ShutdownHookProcessDestroyer processDestroyer = new ShutdownHookProcessDestroyer(); executor.setProcessDestroyer(processDestroyer);
if (timeout <= 0) { timeout = ExecuteWatchdog.INFINITE_TIMEOUT; } ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout); executor.setWatchdog(watchdog);
try { executor.execute(commandLine, cmdHandler); } catch (IOException e) { e.printStackTrace(); } return cf; }
public static void main(String[] args) throws InterruptedException { CommandLine command = CommandLine.parse("ping 127.0.0.1 -t");
CmdHandler result = CmdHelper.run(command, null, 3000); System.out.println(result.resultString());
CmdHelper.exec(command, null, 0).thenAccept(cmdHandler -> { System.out.println(cmdHandler.resultString()); }); } }
|
CmdHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| import org.apache.commons.exec.DefaultExecuteResultHandler; import org.apache.commons.exec.ExecuteException; import org.apache.commons.exec.ExecuteWatchdog; import org.apache.commons.exec.Executor;
public class CmdHandler extends DefaultExecuteResultHandler { Executor executor; Runnable callback; public CmdHandler(Executor executor) { this.executor = executor; } public void setCallback(Runnable callback) { this.callback = callback; } public Executor getExecutor() { return this.executor; } public ExecuteWatchdog getWatchdog() { if (this.executor == null) return null; return this.executor.getWatchdog(); } public String resultString() { String retMsg = "complete"; if (this.getException() != null) { ExecuteWatchdog watchdog = this.getWatchdog(); if (watchdog != null && watchdog.killedProcess()) { retMsg = "timeout"; } else { retMsg = this.getException().getMessage(); } } return this.getExitValue() + ":" + retMsg; }
@Override public void onProcessComplete(int exitValue) { super.onProcessComplete(exitValue); if (callback != null) { callback.run(); } }
@Override public void onProcessFailed(ExecuteException e) { super.onProcessFailed(e); if (callback != null) { callback.run(); } } }
|
参考
- https://www.cnblogs.com/kingcucumber/p/3180146.html
- https://www.jianshu.com/p/73aaec23009d