• 使用 Apache Commons Exec 管理外部进程


    在这里插入图片描述

    😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
    🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
    🎐 个人CSND主页——Micro麦可乐的博客
    🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
    🌺《RabbitMQ》本专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
    🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
    💕《Jenkins实战》专栏主要介绍Jenkins+Docker+Git+Maven的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程
    如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

    前言

    在现代软件开发中,经常需要从 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.commonsgroupId>
        <artifactId>commons-execartifactId>
        <version>1.4.0version>
    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 数据库备份,让大家有更深入的理解。


    在这里插入图片描述

  • 相关阅读:
    大数据时代已经到来,你还在忽视数据的查询与应用吗?
    C++ map和set
    JavaWeb-Servlet
    DDPM(Denoising Diffusion Probabilistic Models)扩散模型简述
    3.4背景图片位置
    概率论的学习和整理--番外11:10球里8红球2白球,抽俩次抽中白球的概率是多少呢? 一个例题的不同方法
    Tomcat安装及配置和常见的问题(2022最新详解、图文教程)
    【CSS】基础使用,层级关系,选择器
    Vue3响应式对象: ref和reactive
    很用心的为你写了 9 道 MySQL 面试题
  • 原文地址:https://blog.csdn.net/lhmyy521125/article/details/139309630