使用 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 数据库备份,让大家有更深入的理解。


相关推荐
james的分享5 天前
大数据领域核心 SQL 优化框架Apache Calcite介绍
大数据·sql·apache·calcite
莫寒清5 天前
Apache Tika
java·人工智能·spring·apache·知识图谱
归叶再无青5 天前
web服务安装部署、性能升级等(Apache、Nginx)
运维·前端·nginx·云原生·apache·bash
忙碌5446 天前
OpenTelemetry实战指南:构建云原生全链路可观测性体系
ios·flink·apache·iphone
悠闲蜗牛�6 天前
Apache Flink实时计算实战指南:从流处理到数据湖仓一体的架构演进
架构·flink·apache
2301_816997887 天前
Apache Commons工具类
apache
心雨⁢⁢⁣7 天前
RocketMq(Apache RocketMQ 5.2.1-SNAPSHOT)消息消费流程
apache·rocketmq·java-rocketmq
切糕师学AI7 天前
Apache ZooKeeper 简介
分布式·zookeeper·apache
忙碌5447 天前
实时流处理架构深度剖析:Apache Flink在实时数仓与风控系统的工程实践
架构·flink·apache
x***r15110 天前
phpstudy_x64_8.1.1.3安装教程(含Apache/MySQL启动与端口修改)
数据库·mysql·apache