淺析Java.lang.ProcessBuilder類

來源:互聯網
上載者:User

標籤:rac   擷取   quartz   通知   常見   user   font   檔案名稱   stack   

       最近由於工作需要把使用者配置的Hive命令在Linux環境下執行,專門做了一個使用者管理介面特地研究了這個不經常用得ProcessBuilder類。所以把自己的學習的資料總結一下。

        

一、概述
      ProcessBuilder類是J2SE 1.5在java.lang中新添加的一個新類,此類用於建立作業系統進程,它提供一種啟動和管理進程(也就是應用程式)的方法。在J2SE 1.5之前,都是由Process類處來實現進程的控制管理。
      每個 ProcessBuilder 執行個體管理一個進程屬性集。它的start() 方法利用這些屬性建立一個新的 Process 執行個體。start() 方法可以從同一執行個體重複調用,以利用相同的或相關的屬性建立新的子進程。 (我在《深入研究java.lang.Runtime類》中講過,進程也可以由Runtime.exec()啟動。)

每個進程產生器(即ProcessBuilder對象)管理這些進程屬性:

     命令 是一個字串列表,它表示要調用的外部程式檔案及其參數(如果有)。在此,表示有效作業系統命令的字串列表是依賴於系統的。例如,每一個總體變數,通常都要成為此列表中的元素,但有一些作業系統,希望程式能自已標幟命令列字串——在這種系  統中,Java 實現可能需要命令確切地包含這兩個元素。 
    環境 是從變數 到值 的依賴於系統的映射。初始值是當前進程環境的一個副本(請參閱 System.getenv())。 
    工作目錄 預設值是當前進程的當前工作目錄,通常根據系統屬性 user.dir 來命名。 
    redirectErrorStream 屬性。最初,此屬性為 false,意思是子進程的標準輸出和錯誤輸出被發送給兩個獨立的流,這些流可以通過 Process.getInputStream() 和 Process.getErrorStream() 方法來訪問。如果將值設定為 true,標準錯誤將與標準輸出合并。這使得關聯錯誤訊息和相應的輸出變得更容易。在此情況下,合并的資料可從 Process.getInputStream() 返回的流讀取,而從 Process.getErrorStream() 返回的流讀取將直接到達檔案尾。

    既然有Process類,那為什麼還要發明個ProcessBuilder類呢?ProcessBuilder和Process兩個類有什麼區別呢? 

      ProcessBuilder為進程提供了更多的控制,例如,可以設定當前工作目錄,還可以改變環境參數。而Process的功能相對來說簡單的多。ProcessBuilder是一個final類,有兩個帶參數的構造方法,你可以通過構造方法來直接建立ProcessBuilder的對象。而Process是一個抽象類別,一般都通過Runtime.exec()和ProcessBuilder.start()來間接建立其執行個體。

 

  注意:
      修改進程構建器的屬性將影響後續由該對象的 start() 方法啟動的進程,但從不會影響以前啟動的進程或 Java 自身的進程。
      ProcessBuilder類不是同步的。如果多個線程同時訪問一個 ProcessBuilder,而其中至少一個線程從結構上修改了其中一個屬性,它必須保持外部同步。 啟動一個使用預設工作目錄和環境的新進程: Process p = new ProcessBuilder("myCommand", "myArg").start(); 下面是一個利用修改過的工作目錄和環境啟動進程的例子:  ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
 Map<String, String> env = pb.environment();
 env.put("VAR1", "myValue");
 env.remove("OTHERVAR");
 env.put("VAR2", env.get("VAR1") + "suffix");
 pb.directory("myDir");
 Process p = pb.start();
 要利用一組明確的環境變數啟動進程,在添加環境變數之前,首先調用 Map.clear()。  二、API預覽
     構造方法摘要 
    ProcessBuilder(List<String> command) 
      利用指定的作業系統程式和參數構造一個進程產生器。 
    ProcessBuilder(String... command) 
      利用指定的作業系統程式和參數構造一個進程產生器。      方法摘要 
    command() 
      返回此進程產生器的作業系統程式和參數。 
    command(List<String> command) 
      設定此進程產生器的作業系統程式和參數。 
    command(String... command) 
      設定此進程產生器的作業系統程式和參數。 
    directory() 
      返回此進程產生器的工作目錄。 
    directory(File directory) 
      設定此進程產生器的工作目錄。 
    environment() 
      返回此進程產生器環境的字串映射視圖。 
    redirectErrorStream() 
      通知進程產生器是否合并標準錯誤和標準輸出。 
    redirectErrorStream(boolean redirectErrorStream) 
      設定此進程產生器的 redirectErrorStream 屬性。 
     start()     使用此進程產生器的屬性啟動一個新進程執行個體Process ,可以操作 Process對象:詳解 
三、常見應用
      若要使用ProcessBuilder建立一個進程,只需要建立ProcessBuilder的一個執行個體,指定該進程的名稱和所需參數。要執行此程式,調用該執行個體上的start()即可。1,下面上一個執行Windows記事本的例子。注意它將要編輯的檔案名稱指定為一個參數。
class PBDemo {         public static void main(String args[]) {                 try {                         ProcessBuilder proc = new ProcessBuilder("notepad.exe", "testfile");                         proc.start();                 } catch (Exception e) {                         System.out.println("Error executing notepad.");                 }         } }
2,ProcessBuilder的應用簡單來說就是,先產生一個ProcessBuilder對象:

ProcessBuilder提供了兩個建構函式,ProcessBuilder(List<String> command) 和 ProcessBuilder(String... command

我這裡使用的是第二個,因為是需要在Linux系統上執行shell指令碼,所以,我的建構函式為:

ProcessBuilder pb = new ProcessBuilder("sh"); (ps:你也可以對應的使用“Python”或者在windows上使用“cmd”)

執行的命令的應用程式已經選好了,那我們的輸入和輸出呢,怎麼設定,這是我們關心的地方。

推薦使用redirectInput(File file) ,讓我們用這個方法來擷取輸入,同理使用redirectOutput(File file)

來處理輸出,如果有錯誤的話,還需要使用redirectError(File file)

由於涉及到的參數都是File類型的,所以,你需要先產生這幾個檔案,然後再使用它們

執行完後,可以去outfile裡面查看執行結果,你也可以把結果讀出後返回,將file.sh和outfile這兩個臨時檔案刪除。

 

package com.pmqin.quartz.domian;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.text.SimpleDateFormat;import java.util.Date;public class ProcessBuildertest {    public static void main(String[] args) {        String file = "!/bin/sh\r\n" // linux 的換行是\n,注意換                    + "a=\‘Hello world\‘\r\n" + "echo $a\r\n";            String result = Process("sh", file,true);    System.out.println(result);        } catch (Exception e) {            System.out.println("Error executing notepad.");        }    }public static String Process(String cmd, String commandlist,boolean isSavefile) throws IOException, InterruptedException {                File input = new File("./file.sh");        createNewFile(input);        PrintWriter print = new PrintWriter(input);        print.append(commandlist);        print.flush();        print.close();                String result = "SUCCESS";        try {            File output = null;            if (isSavefile) {                output = new File("./outfile");                createNewFile(output);            }                        ProcessBuilder pb = new ProcessBuilder(cmd);            pb.redirectErrorStream(true);//如果將值設定為 true,標準錯誤將與標準輸出合并,在此情況下,合并的資料可從 Process.getInputStream() 返回的流讀取            pb.redirectInput(input);            if (isSavefile) {                pb.redirectOutput(output); //表示把輸出重新導向到指定的檔案裡面            }                        Process process = pb.start();//非同步                    // 擷取執行的結果            if (!isSavefile) {                InputStream in = process.getInputStream();//同步                System.out.println("等待執行完成");                String  streamtxt=getInputStream(in);                                System.out.println(streamtxt);            }            if (process.waitFor() != 0) {                //InputStream error = process.getErrorStream();                result="Err";            }            process.destroy();        } catch (IOException e) {            result = "FAIL";            e.printStackTrace();        }        return result;    }/**     * inputStream 檔案流 轉成字串     * @param inputStream 檔案流     * @return     * @throws IOException     */    public static String getInputStream(InputStream inputStream) throws IOException {        StringBuilder stringBuilder = new StringBuilder();        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "gb2312"));        String line = null;        while ((line = bufferedReader.readLine()) != null) {            stringBuilder.append(System.getProperty("line.separator"));            stringBuilder.append(line);        }        return stringBuilder.toString();    }        /**     * 判斷檔案是否存在,不存在就建立     * @param file     * @throws IOException      */    public static void createNewFile(File file) throws IOException {                if (!file.exists()) {                file.createNewFile();        }    }

 

淺析Java.lang.ProcessBuilder類

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.