Java执行shell命令的实现
ice&wind 人气:0前言
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(); }
三、总结
实践是检验真理的唯一标准,工作生活中一定要多总结,记录。如果你觉得有用,点个赞吧。收藏一下也是不错的。
加载全部内容