最經常使用的是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