如何使用JAVA調(diào)用SHELL
通過ProcessBuilder進(jìn)行調(diào)度
這種方法比較直觀,而且參數(shù)的設(shè)置也比較方便, 比如我在實(shí)踐中的代碼(我隱藏了部分業(yè)務(wù)代碼):
ProcessBuilder pb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, param1,
param2, param3);
pb.directory(new File(SHELL_FILE_DIR));
int runningStatus = 0;
String s = null;
try {
Process p = pb.start();
try {
runningStatus = p.waitFor();
} catch (InterruptedException e) {
}
} catch (IOException e) {
}
if (runningStatus != 0) {
}
return;
這里有必要解釋一下幾個(gè)參數(shù):
RUNNING_SHELL_FILE:要運(yùn)行的腳本
SHELL_FILE_DIR:要運(yùn)行的腳本所在的目錄; 當(dāng)然你也可以把要運(yùn)行的腳本寫成全路徑。
runningStatus:運(yùn)行狀態(tài),0標(biāo)識(shí)正常。 詳細(xì)可以看java文檔。
param1, param2, param3:可以在RUNNING_SHELL_FILE腳本中直接通過1,2,$3分別拿到的參數(shù)。
直接通過系統(tǒng)Runtime執(zhí)行shell
這個(gè)方法比較暴力,也比較常用, 代碼如下:
p = Runtime.getRuntime().exec(SHELL_FILE_DIR + RUNNING_SHELL_FILE + " "+param1+" "+param2+" "+param3); p.waitFor();
我們發(fā)現(xiàn),通過Runtime的方式并沒有builder那么方便,特別是參數(shù)方面,必須自己加空格分開,因?yàn)閑xec會(huì)把整個(gè)字符串作為shell運(yùn)行。
可能存在的問題以及解決方法
如果你覺得通過上面就能滿足你的需求,那么可能是要碰壁了。你會(huì)遇到以下情況。
沒權(quán)限運(yùn)行
這個(gè)情況我們團(tuán)隊(duì)的朱東方就遇到了, 在做DTS遷移的過程中,要執(zhí)行包里面的shell腳本, 解壓出來了之后,發(fā)現(xiàn)執(zhí)行不了。 那么就按照上面的方法授權(quán)吧
ProcessBuilder builder = new ProcessBuilder("/bin/chmod", "755", tempFile.getPath());
Process process = builder.start();
int rc = process.waitFor();
java進(jìn)行一直等待shell返回
這個(gè)問題估計(jì)更加經(jīng)常遇到。 原因是, shell腳本中有echo或者print輸出, 導(dǎo)致緩沖區(qū)被用完了! 為了避免這種情況, 一定要把緩沖區(qū)讀一下, 好處就是,可以對(duì)shell的具體運(yùn)行狀態(tài)進(jìn)行l(wèi)og出來。 比如上面我的例子中我會(huì)變成:
ProcessBuilder pb = new ProcessBuilder("./" + RUNNING_SHELL_FILE, keyword.trim(),
taskId.toString(), fileName);
pb.directory(new File(CASPERJS_FILE_DIR));
int runningStatus = 0;
String s = null;
try {
Process p = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((s = stdInput.readLine()) != null) {
LOG.error(s);
}
while ((s = stdError.readLine()) != null) {
LOG.error(s);
}
try {
runningStatus = p.waitFor();
} catch (InterruptedException e) {
}
記得在start()之后, waitFor()之前把緩沖區(qū)讀出來打log, 就可以看到你的shell為什么會(huì)沒有按照預(yù)期運(yùn)行。 這個(gè)還有一個(gè)好處是,可以讀shell里面輸出的結(jié)果, 方便java代碼進(jìn)一步操作。
相關(guān)文章
JUC系列學(xué)習(xí)工具類CountDownLatch詳解
這篇文章主要介紹了JUC系列學(xué)習(xí)工具類CountDownLatch詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可任意參考一下2022-08-08
Java實(shí)現(xiàn)簡(jiǎn)單的RPC框架的示例代碼
本篇文章主要介紹了Java實(shí)現(xiàn)簡(jiǎn)單的RPC框架的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11
Druid連接池未關(guān)閉導(dǎo)致內(nèi)存泄漏問題
這篇文章主要介紹了Druid連接池未關(guān)閉導(dǎo)致內(nèi)存泄漏問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
一些java二進(jìn)制的相關(guān)基礎(chǔ)知識(shí)
這篇文章主要介紹了一些java二進(jìn)制的相關(guān)基礎(chǔ)知識(shí),在Java語(yǔ)言中byte代表最小計(jì)量單位,byte由8位2進(jìn)制數(shù)組成。,需要的朋友可以參考下2019-06-06
Java多線程之readwritelock讀寫分離的實(shí)現(xiàn)代碼
這篇文章主要介紹了Java多線程之readwritelock讀寫分離的相關(guān)內(nèi)容,文中涉及具體實(shí)例代碼,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10
Java實(shí)戰(zhàn)之郵件的撰寫和發(fā)送
這篇文章主要為大家詳細(xì)介紹了通過Java代碼實(shí)現(xiàn)郵件的撰寫和發(fā)送功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,需要的小伙伴們可以學(xué)習(xí)一下2021-11-11

