溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java怎么調(diào)用Shell命令和腳本

發(fā)布時間:2021-02-23 11:11:42 來源:億速云 閱讀:322 作者:清風 欄目:開發(fā)技術(shù)

這篇文章主要為大家展示了Java怎么調(diào)用Shell命令和腳本,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶大家一起來研究并學(xué)習一下“Java怎么調(diào)用Shell命令和腳本”這篇文章吧。

Java可以用來干什么

Java主要應(yīng)用于:1. web開發(fā);2. Android開發(fā);3. 客戶端開發(fā);4. 網(wǎng)頁開發(fā);5. 企業(yè)級應(yīng)用開發(fā);6. Java大數(shù)據(jù)開發(fā);7.游戲開發(fā)等。

1.介紹

有時候我們在Linux中運行Java程序時,需要調(diào)用一些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ù)或設(shè)為null,表示調(diào)用命令將在當前程序執(zhí)行的環(huán)境中執(zhí)行;如果沒有dir參數(shù)或設(shè)為null,表示調(diào)用命令將在當前程序執(zhí)行的目錄中執(zhí)行,因此調(diào)用到其他目錄中的文件和腳本最好使用絕對路徑。各個參數(shù)的含義:

  • cmdarray: 包含所調(diào)用命令及其參數(shù)的數(shù)組。

  • command: 一條指定的系統(tǒng)命令。

  • envp: 字符串數(shù)組,其中每個元素的環(huán)境變量的設(shè)置格式為name=value;如果子進程應(yīng)該繼承當前進程的環(huán)境,則該參數(shù)為 null。

  • dir: 子進程的工作目錄;如果子進程應(yīng)該繼承當前進程的工作目錄,則該參數(shù)為 null。

細心的讀者會發(fā)現(xiàn),為了執(zhí)行調(diào)用操作,JVM會啟一個Process,所以我們可以通過調(diào)用Process類的以下方法,得知調(diào)用操作是否正確執(zhí)行:

abstract int waitFor() 
導(dǎo)致當前線程等待,如有必要,一直要等到由該 Process 對象表示的進程已經(jīng)終止。

進程的出口值。根據(jù)慣例,0 表示正常終止;否則,就表示異常失敗。
另外,調(diào)用某些Shell命令或腳本時,會有返回值,那么我們?nèi)绻东@這些返回值或輸出呢?為了解決這個問題,Process類提供了:

abstract InputStream getInputStream() 
獲取子進程的輸入流。 最好對輸入流進行緩沖。

2.調(diào)用Shell命令

這里為了說明問題,我僅用tar命令進行演示。tar命令是一個打包而不進行壓縮的命令。同時,為了檢查tar的調(diào)用是否被正常執(zhí)行,我將調(diào)用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

如果我不設(shè)置dir或設(shè)dir為null,那么fileName不得不是相對路徑,最好是絕對路徑:

call.callCMD("/root/experiment/hive.tar", "/root/experiment/hive", null);
// OR
call.callCMD("/root/experiment/hive.tar", "/root/experiment/hive");

如果我設(shè)置了dir指向了hive所在的父目錄就好辦多了:

call.callCMD("hive.tar", "hive", "/root/experiment/");

3.調(diào)用Shell腳本

Java調(diào)用Shell命令和調(diào)用Shell腳本的操作一模一樣。我這里介紹另外幾個方面:

  1. 給腳本傳遞參數(shù);

  2. 捕獲調(diào)用的輸出結(jié)果;

  3. envp的使用。

給腳本傳遞參數(shù),這個操作很簡單,無非是把參數(shù)加到調(diào)用命令后面組成String,或String[]。

捕獲調(diào)用輸出信息,前面也提到過用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

我要調(diào)用的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調(diào)用代碼是:

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

以上就是關(guān)于“Java怎么調(diào)用Shell命令和腳本”的內(nèi)容,如果改文章對你有所幫助并覺得寫得不錯,勞請分享給你的好友一起學(xué)習新知識,若想了解更多相關(guān)知識內(nèi)容,請多多關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI