調(diào)用java.lang.Runtime.exec的正確姿勢(shì)分享
調(diào)用java.lang.Runtime.exec的正確姿勢(shì)
今天寫(xiě)一個(gè)用到編譯的程序,遇到了問(wèn)題。
在調(diào)用
runtime.exec("javac HelloWorld.java");
運(yùn)行完美,也就是有生成.class。
而到了
runtime.exec("java HelloWorld >> output.txt");
卻怎么也無(wú)法重定向輸出,連output.txt文件也生成不了。
測(cè)試"echo hello >> 1.txt" 也是不可以,甚是頭疼,于是乎翻閱資料,這才發(fā)現(xiàn)了
一個(gè)認(rèn)識(shí)上的誤區(qū),就是exec(str)中 不能把str完全看作命令行執(zhí)行的command。尤其是str中不可包含重定向 ' < ' ' > ' 和管道符' | ' 。
那么,遇到這樣的指令怎么辦呢?我們接著往下看:
兩種方法
一種是將指令寫(xiě)到腳本中,在runtime.exec()中調(diào)用腳本。這種方法避過(guò)了使用exec(),也是一種思路。
還有一種方法,就是調(diào)用exec()的重載方法:我們來(lái)重點(diǎn)看這種方法:
我們先看一下官方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) 最簡(jiǎn)便適合我們,官方說(shuō)4.exec() 與執(zhí)行6.exec(cmdarray,null,null) 效果是一樣的。那么5.exec.(cmdarray,null)也是一樣的咯?
于是乎,我們可以這樣寫(xiě):
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 );
不過(guò)要注意,如果使用java /home/path/HelloWorld 時(shí),' / '會(huì)被解析成 " . ",從而報(bào)出 “錯(cuò)誤: 找不到或無(wú)法加載主類(lèi) .home.path.HelloWorld ”.
所以,無(wú)法使用全路徑的時(shí)候,我們需要更改一下策略,把 路徑 改到工作目錄dir 中去,比如:
File dir = new File("/home/path/");
然后用其第6種重載方法,把dir作為第三個(gè)參數(shù)傳入即可:
String []cmdarry ={"/bin/bash", "-c", "java HelloWorld >> output.txt"} runtime.exec(cmdarry,null.dir);
當(dāng)然echo , ls 等命令便不受' / '限制了。
*BTW,exec()取得返回值的標(biāo)準(zhǔn)用法詳見(jiàn):runtime.exec()的左膀右臂
小結(jié)一下
當(dāng)命令中包含重定向 ' < ' ' > ' 和管道符' | ' 時(shí),exec(String command)方法便不適用了,需要使用exec(String [] cmdArray) 或者exec(String []cmdarray,String []envp,File dir)來(lái)執(zhí)行。
例如:
exec("echo hello >> ouput.txt"); exec("history | grep -i mvn");
應(yīng)改為:
exec( new String[]{"/bin/sh","-c","echo hello >> ouput.txt"}); exec( new String[]{"/bin/bash","-c","history | grep -i mvn"},null);
Java Runtime.exec()注意事項(xiàng)
Runtime.exec()
用來(lái)執(zhí)行外部程序或命令
1.Runtime.exec() 有四種調(diào)用方法
* 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í)行的結(jié)果或錯(cuò)誤信息
需要用BufferedInputStream 和 BufferReader來(lái)得到,否則程序會(huì)hang
比如得到錯(cuò)誤信息用p.getErrorStream(),然后輸出即可:
BufferedInputStream in = new BufferedInputStream(p.getErrorStream()); BufferedReader br = new BufferedReader(new InputStreamReader(in));
4.Runtime.exec()
不等同于直接執(zhí)行command line命令
啊,我算是在這里吃了苦頭了。Runtime.exec()很有局限性,對(duì)有些命令不能直接把command line里的內(nèi)容當(dāng)作String參數(shù)傳給exec().
比如重定向等命令。舉個(gè)例子:
javap -l xxx > output.txt
這時(shí)要用到exec的第二種重載,即input 參數(shù)為String[]:
Process p = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","javap -l xxx > output.txt"});
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解Idea 2019.2 安裝lombok插件失效問(wèn)題解決
這篇文章主要介紹了詳解Idea 2019.2 安裝lombok插件失效問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10Spring Boot中Redis數(shù)據(jù)庫(kù)的使用實(shí)例
Spring Boot中除了對(duì)常用的關(guān)系型數(shù)據(jù)庫(kù)提供了優(yōu)秀的自動(dòng)化支持之外,對(duì)于很多NoSQL數(shù)據(jù)庫(kù)一樣提供了自動(dòng)化配置的支持。本篇文章主要介紹了Spring Boot中Redis的使用實(shí)例代碼,有興趣的開(kāi)業(yè)了解一下。2017-04-04Feign調(diào)用服務(wù)時(shí)丟失Cookie和Header信息的解決方案
這篇文章主要介紹了Feign調(diào)用服務(wù)時(shí)丟失Cookie和Header信息的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03java中的內(nèi)部類(lèi)詳細(xì)總結(jié)
內(nèi)部類(lèi)不是很好理解,但說(shuō)白了其實(shí)也就是一個(gè)類(lèi)中還包含著另外一個(gè)類(lèi)。如同一個(gè)人是由大腦、肢體、器官等身體結(jié)果組成,而內(nèi)部類(lèi)相當(dāng)于其中的某個(gè)器官之一,例如心臟:它也有自己的屬性和行為(血液、跳動(dòng))2013-10-10IDEA 如何導(dǎo)入別人的javaweb項(xiàng)目進(jìn)行部署
這篇文章主要介紹了IDEA 如何導(dǎo)入別人的javaweb項(xiàng)目進(jìn)行部署,本文給大家分享我的詳細(xì)部署過(guò)程及遇到問(wèn)題解決方法,需要的朋友可以參考下2023-03-03Java數(shù)據(jù)結(jié)構(gòu)中七種排序算法實(shí)現(xiàn)詳解
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)中七種排序算法的實(shí)現(xiàn)方法,排序算法可分為兩大類(lèi),比較類(lèi)排序和非比較類(lèi)排序,顧名思義可知它們是通過(guò)比較來(lái)決定元素間的相對(duì)次序,需要詳細(xì)了解排序算法的朋友可以參考下2024-02-02Java使用Hutool執(zhí)行日期的加法和減法操作方法
使用Hutool進(jìn)行日期的加法和減法操作,可以使用`DateUtil.offsetXXX()`方法來(lái)實(shí)現(xiàn),這些方法會(huì)返回一個(gè)新的日期,而不是在原日期上進(jìn)行修改,本文給大家介紹Java使用Hutool執(zhí)行日期的加法和減法操作方法,感興趣的朋友一起看看吧2023-11-11