使用 Apache Commons Exec 管理外部进程

Micro麦可乐 2024-06-29 14:07:05 阅读 92

在这里插入图片描述

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~

🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志

🎐 个人CSND主页——Micro麦可乐的博客

🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战

🌺《RabbitMQ》本专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战

🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解

💕《Jenkins实战》专栏主要介绍Jenkins+Docker+Git+Maven的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程

如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

使用 Apache Commons Exec 管理外部进程

前言为什么选择 Apache Commons Exec?基本用法高级特性结语

前言

在现代软件开发中,经常需要从 Java 应用程序中启动和管理外部进程。Apache Commons Exec 提供了一个简单且强大的 API,用于管理和控制外部进程。本文将详细介绍如何使用 Apache Commons Exec 管理外部进程,包括其优势、基本用法以及一些高级特性。

在这里插入图片描述

为什么选择 Apache Commons Exec?

Java 原生的 java.lang.ProcessBuilderjava.lang.Runtime.exec() 方法虽然能够启动外部进程,但在处理复杂场景(如超时、流控制和并发管理)时显得力不从心。Apache Commons Exec 提供了以下优势:

简化 API:提供更为简洁和易用的接口。超时控制:支持设置超时时间,防止进程无限期挂起。流处理:提供对标准输入、输出和错误流的灵活处理。可靠的进程销毁:在超时或异常情况下能够可靠地销毁进程。

基本用法

首先,引入 Apache Commons Exec 依赖:目前最新版本为 1.4.0

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-exec</artifactId>

<version>1.4.0</version>

</dependency>

以下是一个基本示例,演示如何使用 Apache Commons Exec 启动一个简单的外部进程:

import org.apache.commons.exec.CommandLine;

import org.apache.commons.exec.DefaultExecutor;

import org.apache.commons.exec.ExecuteException;

public class BasicExecExample {

public static void main(String[] args) {

//不带参数 查看ip指令 博主是MacOS系统

//CommandLine cmdLine = CommandLine.parse("ifconfig");

//带参数

CommandLine cmdLine = new CommandLine("ping");

cmdLine.addArgument("www.baidu.com");

//设置执行器

DefaultExecutor executor = new DefaultExecutor();

try {

//执行命令

executor.execute(cmdLine);

} catch (ExecuteException e) {

System.err.println("Execution failed: " + e.getMessage());

} catch (IOException e) {

System.err.println("IO error: " + e.getMessage());

}

}

}

执行效果

在这里插入图片描述

高级特性

超时控制

使用 ExecuteWatchdog 来设置进程的最大执行时间。如果超时,进程将被自动终止:

import org.apache.commons.exec.ExecuteWatchdog;

public class TimeoutExecExample {

public static void main(String[] args) {

//模拟执行时间

CommandLine cmdLine = new CommandLine("ping");

cmdLine.addArgument("www.baidu.com");

DefaultExecutor executor = new DefaultExecutor();

ExecuteWatchdog watchdog = new ExecuteWatchdog(10000); // 10秒超时

executor.setWatchdog(watchdog);

try {

executor.execute(cmdLine);

} catch (ExecuteException e) {

System.err.println("Execution failed: " + e.getMessage());

} catch (IOException e) {

System.err.println("IO error: " + e.getMessage());

}

}

}

可以看到当 ping 指令在执行10秒后进程自动终止

在这里插入图片描述

流处理

通过 PumpStreamHandler 可以处理进程的标准输出和错误输出。以下示例展示了如何将输出重定向到文件:

import org.apache.commons.exec.PumpStreamHandler;

import java.io.FileOutputStream;

import java.io.IOException;

public class StreamHandlerExample {

public static void main(String[] args) {

CommandLine cmdLine = new CommandLine("ping");

cmdLine.addArgument("www.baidu.com");

DefaultExecutor executor = new DefaultExecutor();

try (FileOutputStream outputStream = new FileOutputStream("output.log");

FileOutputStream errorStream = new FileOutputStream("error.log")) {

PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, errorStream);

executor.setStreamHandler(streamHandler);

int exitValue = executor.execute(cmdLine);

System.out.println("Exit value: " + exitValue);

} catch (IOException e) {

System.err.println("IO error: " + e.getMessage());

}

}

}

带环境变量的执行

你可以为外部进程设置特定的环境变量:

import java.util.HashMap;

import java.util.Map;

public class EnvVarsExample {

public static void main(String[] args) {

CommandLine cmdLine = new CommandLine("env");

DefaultExecutor executor = new DefaultExecutor();

Map<String, String> env = new HashMap<>();

env.put("MY_VAR", "some_value");

try {

int exitValue = executor.execute(cmdLine, env);

System.out.println("Exit value: " + exitValue);

} catch (ExecuteException e) {

System.err.println("Execution failed: " + e.getMessage());

} catch (IOException e) {

System.err.println("IO error: " + e.getMessage());

}

}

}

异步执行

Commons Exec还支持异步执行命令。这对于不需要即时等待命令完成的场景非常有用,比如在后台运行某个长时间的任务。这里我们模拟一下mysql数据库备份

public static void main(String[] args) {

CommandLine cmdLine = CommandLine.parse("bash your-database-backup.sh");

DefaultExecutor executor = new DefaultExecutor();

executor.setExitValue(1);

try {

executor.execute(cmdLine, new ExecuteResultHandler() {

@Override

public void onProcessComplete(int exitValue) {

System.out.println("数据库备份完成,退出值:" + exitValue);

}

@Override

public void onProcessFailed(ExecuteException e) {

System.err.println("数据库备份失败:" + e.getMessage());

}

});

} catch (ExecuteException e) {

System.err.println("Execution failed: " + e.getMessage());

} catch (IOException e) {

System.err.println("IO error: " + e.getMessage());

}

}

结语

Apache Commons Exec 提供了一个功能强大且灵活的 API,用于管理和控制外部进程。通过简化的 API、超时控制、流处理和环境变量设置,开发者可以更轻松地集成和管理外部进程。在实际应用中,合理使用这些特性可以显著提升应用程序的稳定性和可维护性。

通过以上示例,相信你已经对 Apache Commons Exec 有了基本了解和实践经验。下一章节我们就使用 Apache Commons Exec 自动化脚本执行实现 MySQL 数据库备份,让大家有更深入的理解。


在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。