1-10 2,816 views
在一个系统中程序每隔5分钟会通过ProcessBuilder创建进程执行shell脚本。系统运行一段时间后,会报以下错误:
java.io.IOException: Cannot run program “ssh”: java.io.IOException: error=24, Too many open files at java.lang.ProcessBuilder.start(ProcessBuilder.java:460)
通过排查发现是由于进程执行shell脚本后,没有再调用进程的destroy方法。修改后的程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
String cmd = "xxx"; Process process = null; try { //创建ProcessBuilder实例 ProcessBuilder processBuilder = new ProcessBuilder("ssh", "root@xxx.xxx.xxx", cmd); processBuilder.redirectErrorStream(); //创建进程并启动 process = processBuilder.start(); //输入流 BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ""; //读取进程返回的结果 while((line = input.readLine())!= null) { //处理返回的结果 } process.waitFor(); //关闭输入流 input.close(); } catch (Exception e) { logger.error("execute [" + cmd + "] fail", e); } finally { //此处作了修改,调用进程的destroy方法销毁进程 if (process != null) { process.destroy(); } } |
修改后系统运行不再报错。
关于此问题,具体原因如下:
Linux系统对于每个进程能打开的最大文件数有限制(一般为65535,可使用“ulimit -n”命令查看该值)。当通过ProcessBuilder创建进程时,STDIN、STDOUT、STDERR会和Java主进程通过输入、输出流建立管道连接,从而占用文件描述符,当进程执行结束后,若不关闭输入、输出流和销毁进程,则会造成Java主进程文件描述符的泄露。因此,需要在进程执行结束后,关闭输入、输出流,销毁进程。
版权属于: 我爱我家
转载时必须以链接形式注明原始出处及本声明。