Java調用Shell命令和腳本的實現(xiàn)
1.介紹
有時候我們在Linux中運行Java程序時,需要調用一些Shell命令和腳本。而Runtime.getRuntime().exec()方法給我們提供了這個功能,而且Runtime.getRuntime()給我們提供了以下幾種exec()方法:
Process exec(String command) 在單獨的進程中執(zhí)行指定的字符串命令。 Process exec(String[] cmdarray) 在單獨的進程中執(zhí)行指定命令和變量。 Process exec(String[] cmdarray, String[] envp) 在指定環(huán)境的獨立進程中執(zhí)行指定命令和變量。 Process exec(String[] cmdarray, String[] envp, File dir) 在指定環(huán)境和工作目錄的獨立進程中執(zhí)行指定的命令和變量。 Process exec(String command, String[] envp) 在指定環(huán)境的單獨進程中執(zhí)行指定的字符串命令。 Process exec(String command, String[] envp, File dir) 在有指定環(huán)境和工作目錄的獨立進程中執(zhí)行指定的字符串命令。
其中,其實cmdarray和command差不多,同時如果參數(shù)中如果沒有envp參數(shù)或設為null,表示調用命令將在當前程序執(zhí)行的環(huán)境中執(zhí)行;如果沒有dir參數(shù)或設為null,表示調用命令將在當前程序執(zhí)行的目錄中執(zhí)行,因此調用到其他目錄中的文件和腳本最好使用絕對路徑。各個參數(shù)的含義:
- cmdarray: 包含所調用命令及其參數(shù)的數(shù)組。
- command: 一條指定的系統(tǒng)命令。
- envp: 字符串數(shù)組,其中每個元素的環(huán)境變量的設置格式為name=value;如果子進程應該繼承當前進程的環(huán)境,則該參數(shù)為 null。
- dir: 子進程的工作目錄;如果子進程應該繼承當前進程的工作目錄,則該參數(shù)為 null。
細心的讀者會發(fā)現(xiàn),為了執(zhí)行調用操作,JVM會啟一個Process,所以我們可以通過調用Process類的以下方法,得知調用操作是否正確執(zhí)行:
abstract int waitFor() 導致當前線程等待,如有必要,一直要等到由該 Process 對象表示的進程已經(jīng)終止。
進程的出口值。根據(jù)慣例,0 表示正常終止;否則,就表示異常失敗。
另外,調用某些Shell命令或腳本時,會有返回值,那么我們?nèi)绻东@這些返回值或輸出呢?為了解決這個問題,Process類提供了:
abstract InputStream getInputStream() 獲取子進程的輸入流。 最好對輸入流進行緩沖。
2.調用Shell命令
這里為了說明問題,我僅用tar命令進行演示。tar命令是一個打包而不進行壓縮的命令。同時,為了檢查tar的調用是否被正常執(zhí)行,我將調用waitFor()方法。
private void callCMD(String tarName, String fileName, String... workspace){
try {
String cmd = "tar -cf" + tarName + " " + fileName;
// String[] cmd = {"tar", "-cf", tarName, fileName};
File dir = null;
if(workspace[0] != null){
dir = new File(workspace[0]);
System.out.println(workspace[0]);
}
process = Runtime.getRuntime().exec(cmd, null, dir);
// process = Runtime.getRuntime().exec(cmd);
int status = process.waitFor();
if(status != 0){
System.err.println("Failed to call shell's command and the return status's is: " + status);
}
}
catch (Exception e){
e.printStackTrace();
}
}
注意:如果把命令放到一個String[]中時,必須把命令中每個部分作為一個元素存在String[]中,或者是把命令按照空格符分割得到的String[]。
String[] cmd = {"tar", "-cf", tarName, fileName}; //right
String[] cmd = {"tar -cf", tarName, fileName}; //error
為了說明dir參數(shù)的作用,我特地把該Java程序和要打包的目錄hive/放在不同的目錄:
/root/workspace/eclipse/Test/src/edu/wzm/CallShell.java /root/experiment/hive
如果我不設置dir或設dir為null,那么fileName不得不是相對路徑,最好是絕對路徑:
call.callCMD("/root/experiment/hive.tar", "/root/experiment/hive", null);
// OR
call.callCMD("/root/experiment/hive.tar", "/root/experiment/hive");
如果我設置了dir指向了hive所在的父目錄就好辦多了:
call.callCMD("hive.tar", "hive", "/root/experiment/");
3.調用Shell腳本
Java調用Shell命令和調用Shell腳本的操作一模一樣。我這里介紹另外幾個方面:
- 給腳本傳遞參數(shù);
- 捕獲調用的輸出結果;
- envp的使用。
給腳本傳遞參數(shù),這個操作很簡單,無非是把參數(shù)加到調用命令后面組成String,或String[]。
捕獲調用輸出信息,前面也提到過用Process.getInputStream()。不過,建議最好對輸入流進行緩沖:
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
另外,envp是一個String[],并且String[]中的每一個元素的形式是:name=value。如:我的Linux系統(tǒng)中沒有以下環(huán)境變量,但是我把它們寫在Java代碼中,作為envp:
val=2 call=Bash Shell
我要調用的Shell腳本是:/root/experiment/test.sh。
#!/usr/bin/env bash args=1 if [ $# -eq 1 ];then args=$1 echo "The argument is: $args" fi echo "This is a $call" start=`date +%s` sleep 3s end=`date +%s` cost=$((($end - $start) * $args * $val)) echo "Cost Time: $cost"
Java調用代碼是:
private void callScript(String script, String args, String... workspace){
try {
String cmd = "sh " + script + " " + args;
// String[] cmd = {"sh", script, "4"};
File dir = null;
if(workspace[0] != null){
dir = new File(workspace[0]);
System.out.println(workspace[0]);
}
String[] evnp = {"val=2", "call=Bash Shell"};
process = Runtime.getRuntime().exec(cmd, evnp, dir);
// process = Runtime.getRuntime().exec(cmd);
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
}
catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
CallShell call = new CallShell();
call.callScript("test.sh", "4", "/root/experiment/");
}
輸出:
/root/experiment/
The argument is: 4
This is a Bash Shell
Cost Time: 24
到此這篇關于Java調用Shell命令和腳本的實現(xiàn)的文章就介紹到這了,更多相關Java調用Shell命令和腳本內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java發(fā)送http請求的示例(get與post方法請求)
這篇文章主要介紹了Java發(fā)送http請求的示例(get與post方法請求),幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2021-01-01
Mybatis-plus:${ew.sqlselect}用法說明
這篇文章主要介紹了Mybatis-plus:${ew.sqlselect}用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
Java使用Tinify實現(xiàn)圖片無損壓縮(4M無損壓縮到1M)的方法
在當今的數(shù)字化時代,圖片已成為網(wǎng)站、應用和社交媒體中不可或缺的元素,然而,大尺寸的圖片不僅會增加頁面或者客戶端加載時間,還會占用大量的存儲空間,本文將詳細介紹如何利用Tinify壓縮圖片,并將其上傳至OSS,重點介紹圖片壓縮實現(xiàn)方式,需要的朋友可以參考下2024-08-08
springcloud檢索中間件?ElasticSearch?分布式場景的使用
單機的elasticsearch做數(shù)據(jù)存儲,必然面臨兩個問題:海量數(shù)據(jù)存儲問題、單點故障問題,本文重點給大家介紹springcloud檢索中間件?ElasticSearch?分布式場景的運用,感興趣的朋友跟隨小編一起看看吧2023-10-10

