最经常使用的是ant(java工程中流行),maven,及通用的exec(只要有shell脚本如.sh,.bat,.exe,.cmd等).而其实前二者不容易出错,后者却遇到了如下问题:
Caused by: java.io.IOException: Cannot run program "DailyBuild.bat"...java.io.IOException: CreateProcess error=2
而如今的问题是以为<exec>节点的workingdir属性设置正确,而command 属性也是指向了要执行的批处理文件"DailyBuild.bat",为何还要报错呢?因而先把相对路径全改为了绝对,发现不行;又试了把workingdir属性去掉,把command属性写全路径(由于工做目录去掉了,因此必定得写全),发现能运行了,只是报错,由于引用不对了. 这样一来,问题明了了,补回workingdir属性,运行成功!
得出这样的结论,workingdir属性会让人产生错觉使你在command属性中再也不写这个所谓重复的工做目录部分了,而实际上偏偏要写全路径.效果可能相似这样的:)
<exec
workingdir="projects/${project.name}/deploy/build/"
command="projects/${project.name}/deploy/build/DailyBuild.bat"
errorstr="build failed"/> html
http://www.verydemo.com/demo_c128_i15102.htmljava
在执行bat时若是将commnd 改成 cmd /c DailyBuild.bat也能够。shell
Runtime.getRuntime().exec()方法执行bat时,若是bat没有按预期执行,可使用以下形式:apache
Process p = Runtime.getRuntime().exec("cmd /c start D:\\catalina.bat start", null, new File("D:\\apache-tomcat-6.0.35"));
http://www.oschina.net/question/927474_84637
tomcat
java中用Runtime.getRuntime().exec() 调用外部程序, 获取"标准输出流", 总是阻塞.
在网上找了找, 以为应该是"错误输出流"的问题. 果真, 为"错误输出流"单开一个线程读取之, "标准输出流"就再也不阻塞了.
源码以下:网络
/**执行外部程序,并获取标准输出*/ public static String excuteCmd_multiThread(String[] cmd,String encoding) { BufferedReader bReader=null; InputStreamReader sReader=null; try { Process p = Runtime.getRuntime().exec(cmd); /*为"错误输出流"单独开一个线程读取之,不然会形成标准输出流的阻塞*/ Thread t=new Thread(new InputStreamRunnable(p.getErrorStream(),"ErrorStream")); t.start(); /*"标准输出流"就在当前方法中读取*/ BufferedInputStream bis = new BufferedInputStream(p.getInputStream()); if(encoding!=null && encoding.length()!=0) { sReader = new InputStreamReader(bis,encoding);//设置编码方式 } else { sReader = new InputStreamReader(bis,"GBK"); } bReader=new BufferedReader(sReader); StringBuilder sb=new StringBuilder(); String line; while((line=bReader.readLine())!=null) { sb.append(line); sb.append("/n"); } bReader.close(); p.destroy(); return sb.toString(); } catch(Exception e) { e.printStackTrace(); return ErrorString; } finally { } } /**读取InputStream的线程*/ class InputStreamRunnable implements Runnable { BufferedReader bReader=null; String type=null; public InputStreamRunnable(InputStream is, String _type) { try { bReader=new BufferedReader(new InputStreamReader(new BufferedInputStream(is),"UTF-8")); type=_type; } catch(Exception ex) { } } public void run() { String line; int lineNum=0; try { while((line=bReader.readLine())!=null) { lineNum++; //Thread.sleep(200); } bReader.close(); } catch(Exception ex) { } } }
另外, Runtime.getRuntime().exec() 还有一些局限性, 就是没法像cmd那样执行较为复杂的命令. 好比, 输出流的重定向, 如:
他会当即返回, 不会去执行. 可是咱们能够这样作, 可以完成于cmd中同样的工做:
其中 /c 就是"执行后面字符串的命令". 这样就OK了,但同时仍是要注意"错误输出流"的问题,依然要单开一个线程读取.不然同样会阻塞的.app
http://www.xuebuyuan.com/695058.html
ssh
三、Runtime.getRuntime().exec() 路基中含有空格,以下: 异步
Runtime.getRuntime().exec("cmd.exe /c D:\\Program Files\\tece2.1\\tececode\\updateprogram\\updateProgram.exe");
这样讲没法执行,须要在空格的先后加上双引号,而不是在整个路径的先后加双引号,以下: maven
Runtime.getRuntime().exec("cmd.exe /c D:\\Program\" \"Files\\tece2.1\\tececode\\updateprogram\\updateProgram.exe");
或者使用替换方式:
String commandStr="cmd.exe /c"+" " +realPath.realTomcatPath.replace(" ", "\" \"");
Runtime.getRuntime().exec(commandStr);
http://flyeagle.iteye.com/blog/406487
cmd /c start dir 会打开一个新窗口后执行dir指令,原窗口会关闭.hi://apps;c dir 是执行完dir命令后关闭命令窗口,原窗口不会关闭;k start dir 会打开一个新窗口后执行dir指令://apps:
还能够设置工做目录,对执行与工做目录相关的批处理文件是有用的。
File dir = new File("E:\\Product");
Process process = Runtime.getRuntime().exec("E:\\Product\\copy.bat",null,dir);
http://blog.sina.com.cn/s/blog_3d731e9001000ajm.html
今天使用nio编写一个相似ssh的网络客户端,在执行process的时候,出现了一个让人很头疼的bug,废话不说,上代码:
public static void main(String[] args)throws Exception { Process process=Runtime.getRuntime().exec("cmd /c tree"); int status=process.exitValue(); System.out.println(status); BufferedReader reader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line=null; while((line=reader.readLine())!=null) { System.out.println(line); } BufferedReader error=new BufferedReader(new InputStreamReader(process.getErrorStream())); while((line=error.readLine())!=null) { System.out.println(line); } }
在process后面当即调用后
int status=process.exitValue();
出现了
java.lang.IllegalThreadStateException: process has not exited
at java.lang.Win32Process.exitValue(Native Method)
异常,后来一百度发现,jdk实现process时,调用外部命令不是同步的调用,而是异步执行。因此tree命令尚未执行成功就返回,jdk抛出异常。
后来想了一招,就是无论执行如何,先去读取process的InputStream和ErrorInputStream,也就是说
无论外部命令执行的正确与否,都先去执行一次。
//读取正确执行的返回流 BufferedReader info=new BufferedReader(new InputStreamReader(executor.getInputStream())); while((line=info.readLine())!=null) { infoMsg.append(line).append("\n"); } //读取错误执行的返回流 BufferedReader error=new BufferedReader(new InputStreamReader(executor.getErrorStream())); while((line=error.readLine())!=null) { errorMsg.append(line).append("\n"); } //调用exitValue返回值 responseCode=executor.exitValue();
这个时候,再调用exitValue()方法就不会出错了
这是一个具体的实例
int responseCode=0; StringBuilder infoMsg=new StringBuilder(); StringBuilder errorMsg=new StringBuilder(); String line=null; String cmd=Util.isWindows()?("cmd /c "+command):(command); System.err.println("command is "+cmd); Process executor=Runtime.getRuntime().exec(cmd); BufferedReader info=new BufferedReader(new InputStreamReader(executor.getInputStream())); BufferedReader error=new BufferedReader(new InputStreamReader(executor.getErrorStream())); while((line=info.readLine())!=null) { infoMsg.append(line).append("\n"); } while((line=error.readLine())!=null) { errorMsg.append(line).append("\n"); } responseCode=executor.exitValue();
http://kingj.iteye.com/blog/1420586