其他分享
首页 > 其他分享> > Runtime.getRuntime().exec()执行阻塞和不能执行管道命令的问题

Runtime.getRuntime().exec()执行阻塞和不能执行管道命令的问题

作者:互联网

Runtime.getRuntime().exec()执行阻塞和不能执行管道命令的问题

1.不能执行管道命令的处理方式:

windows平台使用 Runtime.getRuntime().exec(String[]{"cmd", "/k", "cmd str"});

linux平台使用 Runtime.getRuntime().exec(String[]{"sh", "-c", "cmd str"});

下面是Process类的完整例子:

String[] cmds = new String[]{"sh", "-c", "cmd str"};
if (System.getProperty("os.name").toLowerCase().contains("windows")) {
    cmds = new String[]{"cmd", "/k", "cmd str"};
}
Process ps = null;
try {
    ps = Runtime.getRuntime().exec(cmds);           
    doInputProcess(ps.getIntputStream());
    doErrorProcess(ps.getErrorStream());
    doOutProcess(ps.getOutputStream());
  // System.out.println("start."); ps.waitFor();
  // System.out.println("done."); } catch (Exception e) { // } finally{ try { if(ps != null)
        ps.destroy(); } catch (Exception ec) { // } }

2.执行阻塞问题

必须要同时处理完输入流process.getInputStream()和输出流process.getOutputStream(),错误流process.getErrorStream()可以不用考虑,并且每个流都需要工作在不同的线程,否则上例中的ps.waitFor();后面的语句永远不会被执行!

我们可以把上例写个JSP web项目验证一下

新建index.jsp文件放在share项目下,代码如下:

<%@page import="java.io.*" contentType="text/html; charset=UTF-8" %>
<%@page import="java.lang.StringBuilder" contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html>
  <head>
    <title>Runtime.getRuntime().exec()</title>
  </head>
  
  <body>

<%!
    void inputProcess(final InputStream in, final JspWriter out, String name){
        //必须是新线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                if(in == null) return;
                try {
                    int a = -1;
                    byte[] b = new byte[2048];
                    while ((a = in.read(b)) != -1) {
                        out.println(new String(b));
                    }
                } catch (Exception e) {                  
                    
                } finally{
                    try {
                        if(in != null ) in.close();
                    } catch (Exception ec) { 
                        
                    }     
                }
            }
        }, name).start();
    }

    void doInputProcess(InputStream in, JspWriter out){
        inputProcess(in, out, "inputProcess");
    }

    void doErrorProcess(InputStream in, JspWriter out){
        inputProcess(in, out, "errProcess");
    }

    void doOutputProcess(OutputStream out){
        try {
            out.close();//直接关闭流
        } catch (Exception ec) { 
            
        }
    }

%>
<% 
    String cmd = request.getParameter("cmd");
    if(cmd != null && !"".equals(cmd)){
        String[] cmds = new String[]{"sh", "-c", cmd};
        if (System.getProperty("os.name").toLowerCase().contains("windows")) {
            cmds = new String[]{"cmd", "/k", cmd};
        }
        Process ps = null;
        try {
            ps = Runtime.getRuntime().exec(cmds);   
            out.println("start.");
            out.println("<pre>");        
            doInputProcess(ps.getInputStream(), out);
            doErrorProcess(ps.getErrorStream(), out);
            doOutputProcess(ps.getOutputStream());
            ps.waitFor();
            out.println("</pre>");
            out.println("done.");
        } catch (Exception e) {                  
            out.println("err.");
        } finally{
            try {
                if(ps != null) ps.destroy();
            } catch (Exception ec) { 
                
            }     
        }
        return;
    }
    if("true".equals(request.getParameter("c"))){
        return;
    }
    out.println("<div style='margin: 20px'>虚拟终端:<input id='command' type='text' value='netstat -an' style='width: 250px;border: none;color: red;background-color: black;'/>"
        + "<a style='color: blue' onclick=\"var m= top.document.getElementById('command').value;if(!m) return false; top.document.getElementById('view-file').setAttribute('src', './index.jsp?cmd=' + encodeURIComponent(m));\" href=\"#\">执行</a>"
        + "</div>");
    out.println("<div style='margin-top: 20px; padding: 5px; height: 500px'>"
        + "<iframe id='view-file' src='./index.jsp?c=true' height='100%' style='width: 100%; height: 100%' frameborder='0'></iframe>"
        + "</div>");
%>
  </body>
</html>

 

 

浏览器访问当前JSP文件,输入网址:http://localhost:8080/share/index.jsp

 

正常执行上面的index.jsp脚本,输入一个命令ipa,服务器相应了200,说明后台没被阻塞

 

 

 

 

当我们将index.jsp中标红的“doOutputProcess(ps.getOutputStream());”这行代码注释掉之后,在执行同一个命令,会发现请求一直处于阻塞状态,done.也没有被打印下来 

 

 

 

 

 

 总结此问题,要想Runtime.getRuntime().exec()这个进程正常退出,不被阻塞需要配合多个线程,并至少关闭ps.getInputStream()和ps.getOutputStream()两个输入输出流

 

标签:ps,exec,getRuntime,println,Runtime,out
来源: https://www.cnblogs.com/muphy/p/13812605.html