使用 Apache Commons Exec 管理外部进程

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

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

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

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

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

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

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

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

使用 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

xml 复制代码
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-exec</artifactId>
    <version>1.4.0</version>
</dependency>

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

java 复制代码
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 来设置进程的最大执行时间。如果超时,进程将被自动终止:

java 复制代码
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 可以处理进程的标准输出和错误输出。以下示例展示了如何将输出重定向到文件:

java 复制代码
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());
        }
    }
}

带环境变量的执行

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

java 复制代码
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数据库备份

java 复制代码
    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 数据库备份,让大家有更深入的理解。


相关推荐
运维全栈笔记1 天前
Linux安装配置Tomcat保姆级教程:从部署到性能调优
linux·服务器·中间件·tomcat·apache·web
❀͜͡傀儡师1 天前
Apache Doris 4.0.0 存算分离手动部署指南
apache·doris 4.0
DolphinScheduler社区4 天前
DolphinScheduler 3.3.2 如何调用 DataX 3.0 + SeaTunnel 2.3.12?附 Demo演示!
java·spark·apache·海豚调度·大数据工作流调度
YaBingSec5 天前
玄机网络安全靶场:Apache HTTPD 解析漏洞(CVE-2017-15715)WP
java·笔记·安全·web安全·php·apache
SuperherRo5 天前
服务攻防-中间件安全&Apache&Tomcat&Jetty&Weblogic&AJP协议&反序列化&CVE漏洞
中间件·tomcat·apache·jetty·weblogic
回忆2012初秋6 天前
时序库.net平台下的推荐 SonnetDB,一文分析清除他与Apache IoTDB的区同
apache·iotdb
家有娇妻张兔兔7 天前
Apache POI 导出 Word 踩坑实录:Word 分栏为什么做不好左右平铺
c#·word·apache·poi·分栏
HashData酷克数据7 天前
官宣:Apache Cloudberry (Incubating) 2.1.0 正式发布!
apache
weixin_394758037 天前
直播间小程序码生成问题修复代码清单
android·小程序·apache
YaBingSec8 天前
玄机靶场—Apache-druid(CVE-2021-25646) WP
java·开发语言·笔记·安全·php·apache