1. 程式人生 > >Java調用本地命令

Java調用本地命令

pan string blog pri strong 說明 shell 腳本 handle 添加

參考:http://blog.csdn.net/zhu_xun/article/details/19539513

http://www.cnblogs.com/kingcucumber/p/3180146.html

一、Process類

ProcessBuilder.start()創建一個本機進程,並返回一個Process子類的一個實例,該實例可以獲取進程的相關信息,也可以控制進程。這個進程沒有自己的終端,它的操作結果io都重定向到了它的父進程,父進程通過getInputStream(),getOutputStream(),getErrorStream()為子進程提供輸入和獲取輸出,而對於io流如果有緩沖大小限制,則可能出現阻塞,導致死鎖情況。

可使用destory()方式強制殺掉子進程,exitValue()返回執行結果,如果子進程需要等待返回,調用waitFor()方法將當前線程等待,直到子進程退出。

二、Runtime類

Runtime.getRuntime().exec() 獲得的就是Process類,exec()方法有多個重載可以使用,針對不同的情況設置不同的參數。另外需要註意的是執行的windows和linux的明林的寫法是不同的。

public static void main(String[] args) {
                String command = "notepad.exe txt.txt";

               
try { Process process = Runtime.getRuntime().exec(command); BufferedInputStream bis = new BufferedInputStream( process.getInputStream()); BufferedReader br = new BufferedReader(new InputStreamReader(bis)); String line;
while ((line = br.readLine()) != null) { System.out.println(line); } process.waitFor(); if (process.exitValue() != 0) { System.out.println("error!"); } bis.close(); br.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }

三、Apache Common-Exec

強烈建議使用apache的第三方庫,該庫提供了更加詳細的設置和監控方法等等。

執行的命令被稱為CommandLine,可使用該類的addArgument()方法為其添加參數,parse()方法將你提供的命令包裝好一個可執行的命令。命令是由執行器Executor類來執行的,DefaultExecutor類的execute()方法執行命令,exitValue也可以通過該方法返回接收。設置ExecuteWatchdog可指定進程在出錯後多長時間結束,這樣有效防止了run-away的進程。此外common-exec還支持異步執行,Executor通過設置一個ExecuteResultHandler類,該類的實例會接收住錯誤異常和退出代碼。

CommandLine cmdLine = new CommandLine("AcroRd32.exe");
cmdLine.addArgument("/p");
    cmdLine.addArgument("/h");
    cmdLine.addArgument("${file}");
    HashMap map = new HashMap();
    map.put("file", new File("invoice.pdf"));
    commandLine.setSubstitutionMap(map);

    DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();

    ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);
    Executor executor = new DefaultExecutor();
    executor.setExitValue(1);
    executor.setWatchdog(watchdog);
    executor.execute(cmdLine, resultHandler);

    // some time later the result handler callback was invoked so we
    // can safely request the exit value
    int exitValue = resultHandler.waitFor();

一、Java中關於ProcessBuilder 和 Runtime 類的介紹

在Java中要想執行腳本或者調用程序必須通過ProcessBuilder 和 Runtime 類,以上兩個類任選一個就行,關於他們的介紹如下:

ProcessBuilder.start() 和 Runtime.exec() 方法都被用來創建一個操作系統進程(執行命令行操作),並返回 Process 子類的一個實例,該實例可用來控制進程狀態並獲得相關信息。
Process 類提供了執行從進程輸入、執行輸出到進程、等待進程完成、檢查進程的退出狀態以及銷毀(殺掉)進程的方法。創建進程的方法可能無法針對某些本機平臺上的特定進程很好地工作,比如,本機窗口進程,守護進程,Microsoft Windows 上的 Win16/DOS 進程,或者 shell 腳本。創建的子進程沒有自己的終端或控制臺。它的所有標準 io(即 stdin、stdout 和 stderr)操作都將通過三個流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父進程。父進程使用這些流來提供到子進程的輸入和獲得從子進程的輸出。因為有些本機平臺僅針對標準輸入和輸出流提供有限的緩沖區大小,如果讀寫子 進程的輸出流或輸入流迅速出現失敗,則可能導致子進程阻塞,甚至產生死鎖。 當沒有 Process 對象的更多引用時,不是刪掉子進程,而是繼續異步執行子進程。 對於帶有 Process 對象的 Java 進程,沒有必要異步或並發執行由 Process 對象表示的進程。
每個ProcessBuilder實例管理一個進程屬性集。ProcessBuilder的start()方法利用這些屬性創建一個新的Process實例。start()方法可以從同一實例重復調用,以利用相同或者相關的屬性創建新的子進程。
不同點:
ProcessBuilder.start() 和 Runtime.exec()傳遞的參數有所不同,Runtime.exec()可接受一個單獨的字符串,這個字符串是通過空格來分隔可執行命令程序和參數的;也可以接受字符串數組參數。而ProcessBuilder的構造函數是一個字符串列表或者數組。列表中第一個參數是可執行命令程序,其他的是命令行執行是需要的參數。
通過查看JDK源碼可知,Runtime.exec最終是通過調用ProcessBuilder來真正執行操作的。

二、Runtime演示示例

1.在windows下調用dos命令:

下面演示了在windows下執行dos命令"chdir",並將執行結果輸出的示例。

public class TestDos {  
  
    /** 
     * 在windows下執行dos命令並在console端輸出 
     *  
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        String strCmd = "chdir";//待執行的dos命令(chdir命令作用是列出當前的工作目錄)  
        Process process = Runtime.getRuntime().exec("cmd /k " + strCmd);//通過cmd程序執行cmd命令  
        //process.waitFor();  
        //讀取屏幕輸出  
        BufferedReader strCon = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        String line;  
        while ((line = strCon.readLine()) != null) {  
            System.out.println(line);  
            }  
    }  
}  

如果不需要進行屏幕輸出的話可以簡寫成如下方式:

public class TestDos {  
  
    /** 
     * 在windows下調用dos命令 
     *  
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        String strCmd = "dos命令";//待執行的dos命令  
        Runtime.getRuntime().exec("cmd /c " + strCmd).waitFor();//通過cmd程序執行dos命令  
    }  
}  

註:執行dos命令時,需在命令前加上"cmd /x"參數,其中x可以為c或者k值,具體說明如下:

cmd /c chdir 是執行完dir命令後關閉命令窗口。
cmd /k chdir 是執行完dir命令後不關閉命令窗口。
cmd /c start chdir 會打開一個新窗口後執行dir指令,原窗口會關閉。
cmd /k start chdir 會打開一個新窗口後執行dir指令,原窗口不會關閉。

2.在windows下調用外部程序:

下面演示了調用QQ程序的過程:

/** 
 * 在windows下調用QQ程序示例 
 * */  
public class CallQQ {  
  
    /** 
     * @param args 
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        Runtime.getRuntime().exec("D:\\Program Files (x86)\\Tencent\\QQ\\QQProtect\\Bin\\QQProtect.exe");  
    }  
}  

3.在Linux下執行shell命令:

下面演示了在Linux中執行shell命令pwd,並顯示執行結果:

/** 
 * 執行Linux的shell命令並在console端輸出結果 
 * */  
public class CallShell {  
  
    /** 
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        String strCmd = "pwd";//執行shell命令  
        Process process = Runtime.getRuntime().exec(strCmd);//通過執行cmd命令調用protoc.exe程序  
        BufferedReader strCon = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        String line;  
        while ((line = strCon.readLine()) != null) {  
            System.out.println("java print:"+line);  
            }  
    }  
}  

4.在Linux下調用shell腳本並輸出結果:

/** 
 * 在linux下調用shell腳本並在console端輸出腳本的執行結果 
 * */  
public class CallShell {  
  
    /** 
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        String strCmd = "/home/zhu/test/test.sh";//待調用shell腳本  
        Process process = Runtime.getRuntime().exec(strCmd);//通過執行cmd命令調用protoc.exe程序  
        BufferedReader strCon = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        String line;  
        while ((line = strCon.readLine()) != null) {  
            System.out.println("java print:"+line);  
            }  
    }  
}  

三、ProcessBuilder使用示例

ProcessBuilder的使用參考如下:

String[] as = new String[]{“待執行命令1”,"待執行命令2",.........};
ProcessBuilder pb = new ProcessBuilder(as);
pb.start();
使用ProcessBuilder可以依次執行多個命令

Java調用本地命令