Java执行Shell命令和Shell脚本

Java技术 潘老师 2年前 (2021-10-08) 2322 ℃ (0) 扫码查看

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.panziye.com/java/3846.html
喜欢 (2)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】