参考一:豆包版
下面为你展示如何使用 Java 的 commons-exec 库来执行命令行并在必要时强制终止它。下面是一个完整的示例代码:
import org.apache.commons.exec.*; import java.io.IOException; public class CommandExecutor { public static void main(String[] args) { CommandExecutor executor = new CommandExecutor(); // 执行一个长时间运行的命令 executor.executeCommand("ping -t 127.0.0.1"); } public void executeCommand(String commandLine) { // 创建命令行对象 CommandLine cmdLine = CommandLine.parse(commandLine); // 创建执行器 DefaultExecutor executor = new DefaultExecutor(); // 设置工作目录 executor.setWorkingDirectory(new java.io.File(System.getProperty("user.dir"))); // 创建一个超时控制 ExecuteWatchdog watchdog = new ExecuteWatchdog(60000); // 设置超时时间为60秒 executor.setWatchdog(watchdog); // 设置执行结果处理器 ExecuteResultHandler resultHandler = new DefaultExecuteResultHandler(); try { // 异步执行命令 executor.execute(cmdLine, resultHandler); // 主线程休眠10秒后尝试强制终止命令 Thread.sleep(10000); // 检查命令是否还在运行 if (!resultHandler.hasResult()) { System.out.println("命令仍在运行,准备强制终止..."); // 使用watchdog强制终止命令 watchdog.destroyProcess(); System.out.println("命令已被强制终止"); } else { System.out.println("命令已完成执行"); } } catch (IOException | InterruptedException e) { e.printStackTrace(); } // 等待命令执行完成 try { resultHandler.waitFor(); int exitValue = resultHandler.getExitValue(); System.out.println("命令执行完成,退出值: " + exitValue); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("等待命令执行完成时被中断"); } catch (ExecuteException e) { System.out.println("命令执行异常,退出值: " + e.getExitValue()); } } }
在使用这段代码时,你需要先在项目里添加 Apache Commons Exec 库的依赖。要是你用的是 Maven 项目,就在 pom.xml
中添加以下依赖:
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-exec</artifactId> <version>1.3</version> </dependency>
此代码具备以下功能:
- 能够异步执行外部命令。
- 可以设置命令的超时时间。
- 能在需要时强制终止命令的执行。
- 会处理命令执行完成后的结果以及可能出现的异常。
你可以根据自身需求对代码进行修改,比如调整超时时间、更改要执行的命令等。
参考二:DeepSeek版
在 Java 中使用 commons-exec
库强制杀死命令行进程,可以通过 ExecuteWatchdog
实现。以下是详细步骤和示例代码:
解决方案
-
添加依赖:在
pom.xml
中添加commons-exec
依赖。 -
创建
ExecuteWatchdog
:用于监控和强制终止进程。 -
主动触发终止:调用
watchdog.destroyProcess()
强制杀死进程。
示例代码
import org.apache.commons.exec.CommandLine; import org.apache.commons.exec.DefaultExecutor; import org.apache.commons.exec.ExecuteException; import org.apache.commons.exec.ExecuteWatchdog; import org.apache.commons.exec.PumpStreamHandler; import java.io.ByteArrayOutputStream; public class ProcessKiller { public static void main(String[] args) throws Exception { // 1. 创建长时间运行的命令(示例:Windows 持续 ping) CommandLine cmd = CommandLine.parse("ping 127.0.0.1 -n 20"); // 执行约 20 秒 // 2. 设置执行器 DefaultExecutor executor = new DefaultExecutor(); executor.setExitValue(0); // 设置成功退出码为 0 // 3. 捕获输出(可选) ByteArrayOutputStream output = new ByteArrayOutputStream(); PumpStreamHandler streamHandler = new PumpStreamHandler(output); executor.setStreamHandler(streamHandler); // 4. 创建看门狗(设置超时时间) ExecuteWatchdog watchdog = new ExecuteWatchdog(2000); // 2秒超时 executor.setWatchdog(watchdog); // 5. 在新线程中执行命令(避免阻塞主线程) Thread execThread = new Thread(() -> { try { executor.execute(cmd); } catch (ExecuteException e) { if (watchdog.killedProcess()) { System.out.println("进程被强制终止!"); } } catch (Exception e) { e.printStackTrace(); } }); execThread.start(); // 6. 等待一段时间后强制终止 Thread.sleep(5000); // 5秒后终止 if (watchdog.isWatching()) { watchdog.destroyProcess(); // 强制杀死进程 System.out.println("已发送终止信号"); } // 7. 打印输出(可选) System.out.println("命令输出:\n" + output.toString()); } }
关键点说明
-
ExecuteWatchdog
:-
通过
setWatchdog()
绑定到执行器。 -
destroyProcess()
方法强制终止进程(调用操作系统的kill
命令)。 -
killedProcess()
检查进程是否被手动终止。
-
-
超时控制:
-
构造函数
ExecuteWatchdog(timeout)
设置自动超时(毫秒)。 -
示例中手动调用
destroyProcess()
主动终止,比自动超时更灵活。
-
-
多线程执行:
-
命令在单独线程中执行,避免阻塞主线程。
-
主线程通过
Thread.sleep()
模拟等待后终止。
-
-
跨平台支持:
-
commons-exec
自动处理不同操作系统(Windows/Linux)的进程终止命令。
-
注意事项
-
资源释放:确保在 finally 块中关闭
ByteArrayOutputStream
(示例省略)。 -
僵尸进程:强制终止可能导致子进程残留,必要时需额外清理。
-
错误处理:检查
ExecuteException
并处理超时或权限问题。
输出结果示例
已发送终止信号 进程被强制终止! 命令输出: 正在 Ping 127.0.0.1 具有 32 字节的数据... 来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128 来自 127.0.0.1 的回复: 字节=32 时间<1ms TTL=128 ...(部分输出)
通过此方案,你可以安全地强制终止由 commons-exec
启动的长时间运行或卡住的命令行进程。