調用java.lang.Runtime.exec的正確姿勢分享
調用java.lang.Runtime.exec的正確姿勢
今天寫一個用到編譯的程序,遇到了問題。
在調用
runtime.exec("javac HelloWorld.java");
運行完美,也就是有生成.class。
而到了
runtime.exec("java HelloWorld >> output.txt");
卻怎么也無法重定向輸出,連output.txt文件也生成不了。
測試"echo hello >> 1.txt" 也是不可以,甚是頭疼,于是乎翻閱資料,這才發(fā)現(xiàn)了
一個認識上的誤區(qū),就是exec(str)中 不能把str完全看作命令行執(zhí)行的command。尤其是str中不可包含重定向 ' < ' ' > ' 和管道符' | ' 。
那么,遇到這樣的指令怎么辦呢?我們接著往下看:
兩種方法
一種是將指令寫到腳本中,在runtime.exec()中調用腳本。這種方法避過了使用exec(),也是一種思路。
還有一種方法,就是調用exec()的重載方法:我們來重點看這種方法:
我們先看一下官方doc[>link<]給我們提供的重載方法:
public Process exec(String command) throws IOExecption public Process exec(String command,String [] envp) throws IOExecption public Process exec(String command,String [] envp,File dir) throws IOExecption public Process exec(String[] cmdarray) throws IOExecption public Process exec(String[] cmdarray,String [] envp) throws IOExecption public Process exec(String[] cmdarray,String [] envp,File dir) throws IOExecption
翻閱其文檔,發(fā)現(xiàn)其重載方法4.exec(String []cmdarray) 最簡便適合我們,官方說4.exec() 與執(zhí)行6.exec(cmdarray,null,null) 效果是一樣的。那么5.exec.(cmdarray,null)也是一樣的咯?
于是乎,我們可以這樣寫:
runtime.exec( new String[]{"/bin/bash", "-c", "java HelloWorld >> output.txt"} );
runtime.exec( new String[]{"/bin/bash", "-c", "java HelloWorld >> output.txt"} ,null );
runtime.exec( new String[]{"/bin/bash", "-c", "java HelloWorld >> output.txt"} ,null,null );
不過要注意,如果使用java /home/path/HelloWorld 時,' / '會被解析成 " . ",從而報出 “錯誤: 找不到或無法加載主類 .home.path.HelloWorld ”.
所以,無法使用全路徑的時候,我們需要更改一下策略,把 路徑 改到工作目錄dir 中去,比如:
File dir = new File("/home/path/");
然后用其第6種重載方法,把dir作為第三個參數(shù)傳入即可:
String []cmdarry ={"/bin/bash", "-c", "java HelloWorld >> output.txt"}
runtime.exec(cmdarry,null.dir);
當然echo , ls 等命令便不受' / '限制了。
*BTW,exec()取得返回值的標準用法詳見:runtime.exec()的左膀右臂
小結一下
當命令中包含重定向 ' < ' ' > ' 和管道符' | ' 時,exec(String command)方法便不適用了,需要使用exec(String [] cmdArray) 或者exec(String []cmdarray,String []envp,File dir)來執(zhí)行。
例如:
exec("echo hello >> ouput.txt");
exec("history | grep -i mvn");
應改為:
exec( new String[]{"/bin/sh","-c","echo hello >> ouput.txt"});
exec( new String[]{"/bin/bash","-c","history | grep -i mvn"},null);
Java Runtime.exec()注意事項
Runtime.exec()用來執(zhí)行外部程序或命令
1.Runtime.exec() 有四種調用方法
* public Process exec(String command);
* public Process exec(String [] cmdArray);
* public Process exec(String command, String [] envp);
* public Process exec(String [] cmdArray, String [] envp);
2.得到程序執(zhí)行返回值, 0為success
需要用waitFor()函數(shù),比如
Process p = Runtime.getRuntime().exec("javac");
(處理.....)
int exitVal = p.waitFor();
3.得到程序執(zhí)行的結果或錯誤信息
需要用BufferedInputStream 和 BufferReader來得到,否則程序會hang
比如得到錯誤信息用p.getErrorStream(),然后輸出即可:
BufferedInputStream in = new BufferedInputStream(p.getErrorStream()); BufferedReader br = new BufferedReader(new InputStreamReader(in));
4.Runtime.exec()
不等同于直接執(zhí)行command line命令
啊,我算是在這里吃了苦頭了。Runtime.exec()很有局限性,對有些命令不能直接把command line里的內(nèi)容當作String參數(shù)傳給exec().
比如重定向等命令。舉個例子:
javap -l xxx > output.txt
這時要用到exec的第二種重載,即input 參數(shù)為String[]:
Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","javap -l xxx > output.txt"});
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Java實現(xiàn)等待所有子線程結束后再執(zhí)行一段代碼的方法
這篇文章主要介紹了Java實現(xiàn)等待所有子線程結束后再執(zhí)行一段代碼的方法,涉及java多線程的線程等待與執(zhí)行等相關操作技巧,需要的朋友可以參考下2017-08-08
Spring項目使用Maven和BCrypt實現(xiàn)修改密碼功能方式
在數(shù)字時代,信息安全尤其是密碼安全至關重要,本文通過實例探討如何在Spring項目中利用Maven和BCrypt實現(xiàn)一個安全的密碼修改功能,我們將從環(huán)境搭建到編寫核心業(yè)務邏輯,再到完成功能測試,確保每一步都遵循最佳安全實踐,通過本文,你將了解到密碼安全的重要性2024-10-10
Java利用opencv實現(xiàn)用字符展示視頻或圖片的方法
這篇文章主要介紹了Java利用opencv實現(xiàn)用字符展示視頻或圖片的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
詳解Struts2中json 相互引用死循環(huán)解決辦法
本篇文章主要介紹詳解Struts2中json 相互引用死循環(huán)解決辦法,具有一定的參考價值,有興趣的可以了解一下。2017-01-01
Tomcat報錯:HTTP Status 500 (Wrapper cannot find servlet class)
這篇文章主要介紹了Tomcat報錯:HTTP Status 500 (Wrapper cannot find servlet class)解決辦法的相關資料,需要的朋友可以參考下2016-11-11

