行业资讯 2025年08月6日
0 收藏 0 点赞 314 浏览 3212 个字
摘要 :

文章目录 一、Runtime方法: 1、介绍 2、执行shell命令 3、执行shell脚本 二、ProcessBuilder方法: 1、执行普通指令 2、执行有输出内容的指令 三、总结 Java开发……




  • 一、Runtime方法:
  • 二、ProcessBuilder方法:
    • 1、执行普通指令
    • 2、执行有输出内容的指令
  • 三、总结

Java开发的项目,部署到Linux系统后,偶尔会使用Java调用Shell命令和脚本,比如修改了某些参数配置需要重启tomcat服务器或者重启系统等等,虽然使用频率不高,但是我们还是有必要了解下如何使用Java执行Shell命令和Shell脚本。JDK给我们提拱了两种实现方案,一种是Runtime.getRuntime().exec() API方法,另一种是通过ProcessBuilder来实现该功能,其中ProcessBuilder更灵活也更可取。

一、Runtime方法:

1、介绍

我们先了解下其具体的方法有哪些:

// 在单独的进程中执行指定的字符串命令
Process exec(String command) 
// 在单独的进程中执行指定命令和变量 
Process exec(String[] cmdarray) 
// 在指定环境的独立进程中执行指定命令和变量
Process exec(String[] cmdarray, String[] envp) 
// 在指定环境和工作目录的独立进程中执行指定的命令和变量
Process exec(String[] cmdarray, String[] envp, File dir) 
// 在指定环境的单独进程中执行指定的字符串命令 
Process exec(String command, String[] envp) 
// 在有指定环境和工作目录的独立进程中执行指定的字符串命令 
Process exec(String command, String[] envp, File dir) 

说明下参数含义:
1)command: 一条指定的系统命令,比如 : echo hello。
2)cmdarray: 包含所调用命令及其参数的数组。
3)envp: 字符串数组,其中每个元素的环境变量的设置格式为name=value;如果子进程应该继承当前进程的环境,则该参数为 null。
4)dir: 子进程的工作目录;如果子进程应该继承当前进程的工作目录,则该参数为 null。
5)Process:调用exec方法后JVM会启动一个Precess进程返回, 我们可以调用如下方法:

// 检测执行是否正确。该方法使当前线程等待,返回0 表示正常终止;否则,就表示异常失败
abstract  int waitFor() 
// 获取返回值。通过输入流获取脚本会指令输出的值。
abstract InputStream  getInputStream()

2、执行shell命令

public void callCmd(String command){
    try {
        Process process = Runtime.getRuntime().exec(command);
        int status = process.waitFor();
        if(status == 0){
            System.out.println("执行成功");
        }else {
            System.out.println("执行失败");
        }
    }catch (Exception e){
        e.printStackTrace();
    }
}

3、执行shell脚本

// path为shell脚本绝对路径
public String callScript(String path) {
    String result = null;
    BufferedReader br = null;
    try {
        Process ps = Runtime.getRuntime().exec(path);
        ps.waitFor();

        br = new BufferedReader(new InputStreamReader(ps.getInputStream()));
        StringBuffer sb = new StringBuffer();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line).append("\\n");
        }
        result = sb.toString();
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        try {
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return result;
}

其他的api方法就不再演示了,可以自行研究下。

二、ProcessBuilder方法:

ProcessBuilder相比Runtime方法更可取,因为能够定制一些细节。例如:

  • 使用builder.directory()方法,改变正在运行Shell命令的工作目录
  • 使用builder.environment()方法,设置自定义键值对作为环境变量
  • 重定向输入和输出流值自定义流
  • 使用build.inheritio()方法将它们都继承到当前JVM进程的流中

ProcessBuilder执行主要分成三步:

  • 构建ProcessBuilder
  • 构建外部命令
  • 执行start

案例代码:

1、执行普通指令

// 使用touch在/usr/test下新建my.txt文件
public void test() throws IOException, InterruptedException {
    // 构建一个命令
    List<String> command = new ArrayList<>();
    // 该命令的位置,可以用 which touch 查找
    command.add("/usr/bin/touch");
    command.add("my.txt");
 
    // 构建一个 processBuilder
    ProcessBuilder processBuilder = new ProcessBuilder();
    // 切换工作目录,也可以不写这个,直接在command 里面 加上
    processBuilder.directory(new File("/usr/test"));
    // command.add("/usr/test")
 
    // 添加命令
    processBuilder.command(command);
    // 执行
    Process start = processBuilder.start();
    if (start.isAlive()) {
      start.waitFor();
    }
  }

2、执行有输出内容的指令

public void test2() throws IOException, InterruptedException {
    // 构建一个命令
    List<String> command = new ArrayList<>();
    // 该命令的位置,可以用 which 查找
    command.add("/bin/ls");
 
    ProcessBuilder processBuilder = new ProcessBuilder();
    processBuilder.directory(new File("/usr/test"));
 
    // 设置为 true 后,错误会和标准输出一样输出
    processBuilder.redirectErrorStream(true);
    processBuilder.command(command);
    Process process = processBuilder.start();
 
    InputStream is = process.getInputStream();
 
    // 使用 hutool 工具类 解析 inputStream
    FastByteArrayOutputStream read = IoUtil.read(is);
    System.out.println(read);
 
    is.close();
    if(process.isAlive()){
      process.waitFor();
    }
}

三、总结

以上就是关于如何使用Java执行Shell命令和Shell脚本的内容,有些具体的操作还需要自己在实践中摸索,不断学习,才能更好地运用自如。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/8128.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号