Java执行Shell命令和Shell脚本

IT 文章4年前 (2021)发布 小编
0 0 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进程返回, 我们可以调用如下方法:

ad

程序员导航

优网导航旗下整合全网优质开发资源,一站式IT编程学习与工具大全网站

// 检测执行是否正确。该方法使当前线程等待,返回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方法更可取,因为能够定制一些细节。例如:
[list]使用builder.directory()方法,改变正在运行Shell命令的工作目录
使用builder.environment()方法,设置自定义键值对作为环境变量
重定向输入和输出流值自定义流
使用build.inheritio()方法将它们都继承到当前JVM进程的流中[/list]
ProcessBuilder执行主要分成三步:

[list]构建ProcessBuilder
构建外部命令
执行start[/list]
案例代码:

1、执行普通指令

// 使用touch在/usr/test下新建my.txt文件
public void test() throws IOException, InterruptedException {
    // 构建一个命令
    List 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 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脚本的内容,有些具体的操作还需要自己在实践中摸索,不断学习,才能更好地运用自如。

ad

AI 工具导航

优网导航旗下AI工具导航,精选全球千款优质 AI 工具集

© 版权声明

相关文章

暂无评论

暂无评论...