Java执行shell命令的实现

 更新时间:2023年01月12日 10:57:02   作者:ice&wind  
本文主要介绍了Java执行shell命令的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

java执行shell命令的方式有很多种,但是在应用的过程中,我们可能会遇上一些特殊的情况,导致执行脚本失败,不生效的场景。

一、案例

场景

java服务,如果需要服务自动重启。那么我们通过java执行shell命令,使用常用jdk的方法:Runtime.getRuntime().exec(command)的方式,重启服务,可能会导致重启失败。

原因

  • java执行本地命令启动的是一个子进程处理,默认情况下子进程与父进程I/O通过管道相连(ProcessBuilder.Redirect.PIPE)
  • 当服务执行自身重启命令时,父进程关闭导致管道连接中断,将导致子进程也崩溃,而无法完成后续启动

解决方案

  • 设置子进程的I/O源或目标将与当前进程的相同,两者相互独立
  • 设置子进程IO输出重定向到指定文件

这里我们采用第一种解决方案

ProcessBuilder pb = new ProcessBuilder("service","java-service","restart");
pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
pb.redirectInput(ProcessBuilder.Redirect.INHERIT);
pb.start();

ProcessBuilder 也是J2SE1.5 就有了的类。此类用于创建操作系统进程,它提供一种启动和管理进程(也就是应用程序)的方法。在J2SE 1.5之前,都是由Process类处来实现进程的控制管理。

static ProcessBuilder.Redirect    DISCARD    
表示将丢弃子进程输出。
static ProcessBuilder.Redirect    INHERIT    
表示子进程I / O源或目标将与当前进程的相同。
static ProcessBuilder.Redirect    PIPE    
表示子进程I / O将通过管道连接到当前Java进程。

ProcessBuilder 可配置执行脚本的子进程I / O源或目标将与当前进程的相同。绑定之后,执行重启,就能成功,管道不会断开。

ProcessBuilder 可参考连接:

ProcessBuilder api
ProcessBuilder 中文文档

二、拓展

创建临时脚本,执行shell命令

<dependency>
   <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

可直接复制使用,注意引入maven包

public static String runAndResult(String cmd){
        StringBuilder sb = new StringBuilder();
        BufferedReader br = null;
        boolean execFlag = true;
        String uuid = UUID.randomUUID().toString().replace("-","");
        String tempFileName = "./temp" + uuid +".sh";
        try {
            String osName = System.getProperty("os.name").toUpperCase(Locale.ENGLISH);
            if (osName.matches("^(?i)LINUX.*$") || osName.contains("MAC")) {
                FileWriter execute_fw = new FileWriter(tempFileName);
                BufferedWriter execute_bw=new BufferedWriter(execute_fw);
                execute_bw.write(cmd + "\n");
                execute_bw.close();
                execute_fw.close();
                String command ="bash " + tempFileName;
                Process p = Runtime.getRuntime().exec(command);
                p.waitFor();
                br = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(System.lineSeparator());
                    sb.append(line);
                }
                br.close();
                br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
                while ((line = br.readLine()) != null) {
                    sb.append(System.lineSeparator());
                    sb.append(line);
                    if (line.length() > 0){
                        execFlag = false;
                    }
                }
                br.close();
                if (execFlag){
                }else {
                    throw new RuntimeException(sb.toString());
                }
            }else {
                throw new RuntimeException("不支持的操作系统类型");
            }
        } catch (Exception e) {
            log.error("执行失败",e);
        }finally {
            if (br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    log.error("io异常",e);
                }
            }
            FileUtils.deleteQuietly(new File(tempFileName));
        }
        return sb.toString();
    }

三、总结

实践是检验真理的唯一标准,工作生活中一定要多总结,记录。如果你觉得有用,点个赞吧。收藏一下也是不错的。

到此这篇关于Java执行shell命令的实现的文章就介绍到这了,更多相关Java执行shell内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中Lombok的@Builder注解注意事项

    Java中Lombok的@Builder注解注意事项

    这篇文章主要介绍了Java中Lombok的@Builder注解注意事项,使用Lombok也会造成很多问题,尤其@Builder 有个很大的坑,已经见过好几次由于使用@Builder注解导致默认值失效的问题,如果测试时没有在意这个问题,就很容易引发线上问题,需要的朋友可以参考下
    2023-12-12
  • Java 新特性之Option示例详解

    Java 新特性之Option示例详解

    使用Optional开发时要注意正确使用Optional的“姿势”,特别注意不要使用3.2节提到的错误示范,谨慎使用isPresent()和get()方法,尽量多使用map()、filter()、orElse()等方法来发挥Optional的作用,对Java  Option相关知识感兴趣的朋友一起看看吧
    2024-02-02
  • windows定时器配置执行java jar文件的方法详解

    windows定时器配置执行java jar文件的方法详解

    这篇文章主要给大家介绍了关于windows定时器配置执行java jar文件的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • SpringBoot3中Spring WebFlux SSE服务器发送事件的实现步骤

    SpringBoot3中Spring WebFlux SSE服务器发送事件的实现步骤

    本文介绍了如何使用SpringBoot3和响应式编程实现服务器发送事件(SSE),并讨论了其在实时数据推送场景中的优势,通过示例代码,展示了如何创建SSE控制器、客户端接收数据以及优化与扩展,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • 图解Java中归并排序算法的原理与实现

    图解Java中归并排序算法的原理与实现

    归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。本文将通过图片详解插入排序的原理及实现,需要的可以参考一下
    2022-08-08
  • Spring MVC返回的json去除根节点名称的方法

    Spring MVC返回的json去除根节点名称的方法

    这篇文章主要介绍了Spring MVC返回的json去除根节点名称的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • SpringBoot集成极光推送的实现代码

    SpringBoot集成极光推送的实现代码

    工作中经常会遇到服务器向App推送消息的需求,一般企业中选择用极光推送的比较多,本文就介绍了SpringBoot集成极光推送的实现代码,感兴趣的可以了解一下
    2023-08-08
  • 浅谈Java8对字符串连接的改进正确姿势

    浅谈Java8对字符串连接的改进正确姿势

    这篇文章主要介绍了Java8:对字符串连接的改进,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • SpringBoot去除参数前后空格和XSS过滤

    SpringBoot去除参数前后空格和XSS过滤

    本文主要介绍了SpringBoot去除参数前后空格和XSS过滤,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • java中struts2实现文件上传下载功能

    java中struts2实现文件上传下载功能

    这篇文章主要介绍了java中struts2实现文件上传下载功能的方法,以实例形式分析了struts2文件上传下载功能的实现技巧与相关问题,具有一定的参考借鉴价值,需要的朋友可以参考下
    2016-05-05

最新评论