转贴请注明出处:http://blog.csdn.com/froole
但是,这里还有一点需要注意——那就是shell(DOS)中的特殊符号。
因为用Java作为后台程序的系统,多运行于Unix/Linux,以下的介绍将基于如何shell来展开讨论。
假设,系统需要通过提取某个命令的标准输出,来进行某项处理。例如,搜索/路径下的xml文件并对结果处理,如下:
find / -name "*.xml" -type f | xargs java 相应程序
如果按照常规的方式,将以上的几个字串直接传递给Runtime.exec的参数,通过CommandExec的实现方法如下:
- CommandExec exec = new CommandExec();
- Process process = exec.exec(new String(){"find", "/", "-name", "/"*.xml/"", "-type", "f", "|", "xargs", "java", "相应程序"});
但是,实际结果将事与愿违,因为,在解析"|"的时候是以特殊符号来解析,而JVM将把"|"作为普通的字符串来处理。
在通常的处理中,这种功能可以屏蔽命令溢出的漏洞,但是在特殊需求的时候,就不方便了。
当然,在特殊需求下也有解决方法,可以如下执行以下命令:
- CommandExec exec = new CommandExec();
- Process process = exec.exec(new String(){"shell", "-c", "/"find / -name '*.xml' -type f | xargs java 相应程序/""});
也就是把要执行的命令作为shell的一个参数让Runtime.exec执行,为shell命令加上-c参数就可以正常执行目标命令了。
细心的读者已经看出,用上面的方法,有一个缺点就是,如果动态生成命令,很容易发生命令溢出的漏洞。
这里有一个解决方法,就是设定一个前提,被执行命令,文字串都必须以单引号包含,那样就比较容易escape了。
escape的方法可以如下定义,并添加到CommandExec当中。
- /**
- *
- * 对shell字串进行escape
- *
- * @param s 对象字串
- * @return 返回escape之后的shell字串
- */
- public static String escapeShellSpecialCharacters(String s) {
- StringBuilder sb = new StringBuilder(s.length() + 128);
- sb.append('/'');
- for (int i = 0; s != null && i < s.length(); i++) {
- char c = s.charAt(i);
- if (c == '/'') {
- sb.append('//');
- }
- sb.append(c);
- }
- sb.append('/'');
- return sb.toString();
- }
到此为止,在Java中执行外部命令的方法以及注意点基本叙述完毕。但是,最后还有一点必须注意的就是JVM本身存在的一个漏洞。
这个漏洞的现象是,当被执行的外部命令,标准输出的量比较大的时候,程序会无故锁死。
特别是在JDK1.3版本尤为明显,在新版本中仍旧存在此漏洞。
不过,通过外部命令的执行方式,可以避免此漏洞的出现——通过重定向避免标准输出。
CommandExec的执行方法如下:
- CommandExec exec = new CommandExec();
- Process process = exec.exec(new String(){"shell", "-c", "/"find / -name '*.xml' -type f | xargs java 相应程序 > /dev/null/""});
- 浅析Java执行外部命令的几个要点(1)
- 浅析Java执行外部命令的几个要点(2)
- 浅析Java执行外部命令的几个要点(3)
- 浅析Java执行外部命令的几个要点(4)
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
转贴请注明出处: http://blog.youkuaiyun.com/froole