一、介紹
有時候我們在Linux中運行Java程序時,需要調用一些Shell命令和腳本。而Runtime.getRuntime().exec()方法給我們提供了這個功能,而且Runtime.getRuntime()給我們提供了以下幾種exec()方法:
Process exec(String command)
在單獨的進程中執行指定的字符串命令。
Process exec(String[] cmdarray)
在單獨的進程中執行指定命令和變量。
Process exec(String[] cmdarray, String[] envp)
在指定環境的獨立進程中執行指定命令和變量。
Process exec(String[] cmdarray, String[] envp, File dir)
在指定環境和工作目錄的獨立進程中執行指定的命令和變量。
Process exec(String command, String[] envp)
在指定環境的單獨進程中執行指定的字符串命令。
Process exec(String command, String[] envp, File dir)
在有指定環境和工作目錄的獨立進程中執行指定的字符串命令。
其中,其實cmdarray和command差不多,同時如果參數中如果沒有envp參數或設為null,表示調用命令將在當前程序執行的環境中執行;如果沒有dir參數或設為null,表示調用命令將在當前程序執行的目錄中執行,因此調用到其他目錄中的文件和腳本最好使用絕對路徑。各個參數的含義:
- cmdarray: 包含所調用命令及其參數的數組。
- command: 一條指定的系統命令。
- envp: 字符串數組,其中每個元素的環境變量的設置格式為name=value;如果子進程應該繼承當前進程的環境,則該參數為 null。
- dir: 子進程的工作目錄;如果子進程應該繼承當前進程的工作目錄,則該參數為 null。
細心的讀者會發現,為了執行調用操作,JVM會啟一個Process,所以我們可以通過調用Process類的以下方法,得知調用操作是否正確執行:
abstract int waitFor() 導致當前線程等待,如有必要,一直要等到由該 Process 對象表示的進程已經終止。
二、調用Shell腳本
1、獲取鍵盤輸入
BufferedReader reader = null; try{ reader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("請輸入IP:"); String ip = reader.readLine();
上述指令基本很常見:
1、創建讀入器:BufferReader
2、將數據流載入BufferReader,即InputStreamReader
3、將系統輸入載入InputStreamReader中
4、然后利用reader獲取數據。
2、構建指令
shell運行腳本指令為 sh **.sh args,其實這個格式與java格式相同。
我的腳本為:
#!/bin/sh
#根據進程名殺死進程
echo "This is a $call"
if [ $# -lt 2 ]
then
echo "缺少參數:procedure_name和ip"
exit 1
fi
echo "Kill the $1 process"
PROCESS=`ps -ef|grep $1|grep $2|grep -v grep|grep -v PPID|awk '{ print $2}'`
for i in $PROCESS
do
echo "Kill the $1 process [ $i ]"
done
其實所有准備若當,就是無法讀取里面的數據,執行shell指令,原因就是:
注意事項:
1.shell腳本必須有執行權限,比如部署后chmod -R 777 /webapps
2.shell文件,必須是UNIX格式,ANSI編碼格式,否則容易出問題(可以用notepad++,編輯->文檔格式轉換,格式->轉為ANSI格式(UNIX格式)
3、java程序
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * @author :dongbl * @version : * @Description: * @date :9:19 2017/11/14 */ public class TestBash { public static void main(String [] args){ BufferedReader reader = null; try{ reader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("請輸入IP:"); String ip = reader.readLine(); String bashCommand = "sh "+ "/usr/local/java/jdk1.8.0_121/lib/stopffmpeg.sh" + " ffmpeg " + ip; // String bashCommand = "chmod 777 " + "/usr/local/java/jdk1.8.0_121/lib/stopffmpeg.sh" ; // String bashCommand = "kill -9" + ip; System.out.println(bashCommand); Runtime runtime = Runtime.getRuntime(); Process pro = runtime.exec(bashCommand); int status = pro.waitFor(); if (status != 0) { System.out.println("Failed to call shell's command "); } BufferedReader br = new BufferedReader(new InputStreamReader(pro.getInputStream())); StringBuffer strbr = new StringBuffer(); String line; while ((line = br.readLine())!= null) { strbr.append(line).append("\n"); } String result = strbr.toString(); System.out.println(result); } catch (IOException ec) { ec.printStackTrace(); } catch (InterruptedException ex){ ex.printStackTrace(); } } }
其中文件路徑為絕對路徑,這點需要注意。
三、調試心得
在調試shell腳本執行過程中,反了幾個錯
1、構建指令不對
1、開始指令為:
String bashCommand = "/usr/local/java/jdk1.8.0_121/lib/stopffmpeg.sh "+ " ffmpeg " + ip;
程序報錯,權限不足。
2、此時修改為:
String bashCommand = "chmod 777 "+"/usr/local/java/jdk1.8.0_121/lib/stopffmpeg.sh "+ " ffmpeg " + ip;
記住一定注意空格(格式)但此時依然無法指定腳本指令。3、在發現格式不對后,修改后,還是不行,此時指令為:
String bashCommand = "sh "+ "/usr/local/java/jdk1.8.0_121/lib/stopffmpeg.sh" + " ffmpeg " + ip;
2、文件格式不對
這是無法讀取內容的關鍵原因,因為sh文件是在Windows系統下生成的,所以需要將格式修改為linux格式的,即(UNIX格式)
此時網上程序可以了,然后看到指令不同,修改指令即可以了。
最后終於調通了,看來格式經驗不足啊
四、參考文獻