参考一:豆包版
下面为你展示如何使用 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 启动的长时间运行或卡住的命令行进程。