调用Runtime.getRuntime().exec()执行Linux脚本防挂死和返回脚本输出
1、在实际开发中,使用Runtime.getRuntime().exec()执行Linux脚本时,需要同时读取标准输出流与错误输出流缓冲区数据,因为操作系统缓冲区大小有限制,不及时处理会导致缓冲区占满而挂住,这种问题发生在于开发人员对该接口不了解而引发Bug。
具体可以通过使用两个线程同时去读错误和标准输出流缓冲区数据,然后用proc.waitFor()可以获取执行的结果。这种事最常见的场景,只关注脚本执行结果。
2、但在实际开发中,通过Runtime.getRuntime().exec()执行Linux脚本时,不仅仅要关注脚本执行结果,同时还需要关注脚本执行返回的屏显信息,这个时候使用proc.waitFor()虽然能获取结果,但是屏显信息总是有时候有时候没有,是因为脚本执行完就有结果返回了,但是子线程读取缓冲区数据并不一定就执行完了,所以这种场景下,我们需要等待读取缓冲数据的脚本执行完后,再返回结果。
PS:这个是本人实际开发中遇到的一个问题,使用了父线程等待子线程的方式来实现的,能够解决问题,还有没有其他方式,需要进一步去尝试。
代码主要如下:
import java.util.ArrayList; import java.util.List; public class ExecuteScript { public static void main(String[] args) { System.exit(ececute(args[0], true)); } public static int ececute(String cmd, boolean isNeedPrint) { Process proc = null; int result = -1; try { List<StreamReader> list = new ArrayList<StreamReader>(); proc = Runtime.getRuntime().exec(cmd); StreamReader error = new StreamReader(proc.getErrorStream(), "Error"); StreamReader output = new StreamReader(proc.getInputStream(), "Output"); if (isNeedPrint) { list.add(error); list.add(error); } error.start(); output.start(); if (isNeedPrint) { for (StreamReader sr : list) { sr.join(); } } result = proc.waitFor(); } catch (Exception e) { e.printStackTrace(); } finally { proc.destroy(); } return result; } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class StreamReader extends Thread { InputStream is; String type; StreamReader(InputStream is, String type) { this.is = is; this.type = type; } public void run() { InputStreamReader isr = null; BufferedReader br = null; try { isr = new InputStreamReader(is); br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException ioe) { ioe.printStackTrace(); } finally { close(isr, br); } } public void close(InputStreamReader isr, BufferedReader br) { if (null != br) { try { br.close(); } catch (IOException e) { br = null; } } if (null != isr) { try { isr.close(); } catch (IOException e) { isr = null; } } } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。