2010-08-12 94 views
14

我需要執行一個執行另一個Java應用程序的批處理文件。 我不在乎它是否成功執行,我不必捕捉任何錯誤。從Java執行另一個應用程序

可以用ProcessBuilder做到這一點嗎?如果我不捕捉錯誤會有什麼後果?

但是,我的要求只是執行另一個Java應用程序。

回答

4

我假設你知道如何使用ProcessBuilder執行該命令。

從Java執行命令總是應該從進程讀取stdout和stderr流。否則,可能會發生緩衝區已滿並且由於寫入其stdout或stderr塊而​​導致進程無法繼續的情況。

+0

有什麼辦法可以啓動另一個應用程序,並忽略進程中的stdout和stderr流。 – user234194 2010-08-12 15:10:05

+0

也許你會創建一個'bat'文件,將執行命令的輸出重定向到「dev-null」。 – Mot 2010-08-13 06:27:18

1

如果你不關心的返回值,你可以只使用Runtime.getRuntime().exec("path.to.your.batch.file");

+0

關於stdout和stderr流從進程中獲得滿的情況如何。 – user234194 2010-08-12 15:10:46

+0

不知道你想要跑什麼,這有點難以分辨。我發現SQL Server的BCP等程序在exec'd和請求stdout和stderr流時不會正確報告錯誤,因此這取決於您的子進程。如果它沒有任何輸出,那麼不用擔心,當過程完成時,stdout和stderr將與您的'Process'對象一起被垃圾回收。 – 2010-08-12 15:15:43

+0

我有一個簡單的問題,如果我一旦執行另一個Java應用程序,我不能做process.destroy。這不會幫助stdout/err充滿,或者我正在談論完全不同的事情。因爲,一旦另一個應用程序啓動,我可以退出我的應用程序。 – user234194 2010-08-12 15:22:11

29

Runtime.getRuntime().exec()做法是相當麻煩的,因爲你很快就會找到答案。

看看Apache Commons Exec項目。它抽象化了許多與使用Runtime.getRuntime().exec()ProcessBuilder API相關的常見問題。

很簡單:

String line = "myCommand.exe"; 
CommandLine commandLine = CommandLine.parse(line); 
DefaultExecutor executor = new DefaultExecutor(); 
executor.setExitValue(1); 
int exitValue = executor.execute(commandLine); 
+1

這個答案保存了我的生活。謝謝 – Valath 2014-05-04 04:35:32

4

您可以執行批處理指令,或使用

Runtime.getRuntime().exec(cmd); 
  • CMD的命令或TE應用程序路徑中的任何其他應用程序。

而且喲可以等待執行並獲得返回代碼(以檢查其正確執行),此代碼:

Process p = Runtime.getRuntime().exec(cmd); 
    p.waitFor(); 
    int exitVal = p.exitValue(); 

將有更多不同類型的呼叫這裏 http://www.rgagnon.com/javadetails/java-0014.html

的完整說明
+4

Process.waitFor()實際上會返回進程的退出代碼,因此您可以將最後兩行合併爲「int.exitVal = p.waitFor();」 – 2011-01-21 07:30:01

22

是的,它可以使用ProcessBuilder。

的ProcessBuilder例如:

import java.io.*; 
import java.util.*; 

public class CmdProcessBuilder { 
    public static void main(String args[]) 
    throws InterruptedException,IOException 
    { 
    List<String> command = new ArrayList<String>(); 
    command.add(args[0]); 


    ProcessBuilder builder = new ProcessBuilder(command); 
    Map<String, String> environ = builder.environment(); 

    final Process process = builder.start(); 
    InputStream is = process.getInputStream(); 
    InputStreamReader isr = new InputStreamReader(is); 
    BufferedReader br = new BufferedReader(isr); 
    String line; 
    while ((line = br.readLine()) != null) { 
     System.out.println(line); 
    } 
    System.out.println("Program terminated!"); 
    } 
} 

檢查這些例子:

http://www.rgagnon.com/javadetails/java-0014.html

http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-processbuilder.html

+0

線程「主」java.lang.ArrayIndexOutOfBoundsException中的異常:0 \t at RunClByJava.main(RunClByJava.java:94) – 2017-04-26 06:17:46

4

下面是如何使用ProcessBuilder執行遠程應用程序的例子。既然你不關心輸入/輸出和/或錯誤,你可以做如下:

List<String> args = new ArrayList<String>(); 
args.add ("script.bat"); // command name 
args.add ("-option"); // optional args added as separate list items 
ProcessBuilder pb = new ProcessBuilder (args); 
Process p = pb.start(); 
p.waitFor(); 

waitFor()方法會等到進程已繼續之前結束。此方法返回進程的錯誤代碼,但由於您不關心它,因此我沒有將它放在示例中。

2

我知道這是一個較老的線程,但我認爲它可能是值得我放入我的實現,因爲我發現此線程試圖做與OP一樣的事情,除了根級別訪問,但沒有真的找到我正在尋找的解決方案。下面的方法創建一個靜態根級別shell,用於僅執行命令而不考慮錯誤檢查或者即使命令成功執行。

我使用它創建的Android手電筒應用程序,可以將LED設置爲不同級別的亮度。通過消除所有錯誤檢查和其他絨毛,我可以讓LED在少至3ms的時間內切換到指定的亮度級別,這爲LightTones(帶光的RingTones)打開了大門。關於應用程序本身的更多細節可以在這裏找到:http://forum.xda-developers.com/showthread.php?t=2659842

以下是整個類。

public class Shell { 
    private static Shell rootShell = null; 
    private final Process proc; 
    private final OutputStreamWriter writer; 

    private Shell(String cmd) throws IOException { 
     this.proc = new ProcessBuilder(cmd).redirectErrorStream(true).start(); 
     this.writer = new OutputStreamWriter(this.proc.getOutputStream(), "UTF-8"); 
    } 

    public void cmd(String command) { 
     try { 
      writer.write(command+'\n'); 
      writer.flush(); 
     } catch (IOException e) { } 
    } 

    public void close() { 
     try { 
      if (writer != null) { writer.close(); 
       if(proc != null) { proc.destroy(); } 
      } 
     } catch (IOException ignore) {} 
    } 

    public static void exec(String command) { Shell.get().cmd(command); } 

    public static Shell get() { 
     if (Shell.rootShell == null) { 
      while (Shell.rootShell == null) { 
       try { Shell.rootShell = new Shell("su"); //Open with Root Privileges 
       } catch (IOException e) { } 
      } 
     } 
     return Shell.rootShell; 
    } 
} 

然後隨時隨地在我的應用程序運行一個命令,例如改變LED的亮度,我只要致電:

Shell.exec("echo " + bt.getLevel() + " > "+ flashfile); 
1

下面代碼片段寫入編譯和使用的ProcessBuilder運行外部JAVA程序,我們也可以運行任何外部程序。確保必須在OS環境中設置JAVA_HOME。看more

package com.itexpert.exam; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 

public class JavaProcessBuilder { 
/** 
* Provide absolute JAVA file path 
*/ 
private static final String JAVA_FILE_LOCATION = "D:\\Test.java"; 

public static void main(String args[]) throws IOException{ 
    String command[] = {"javac",JAVA_FILE_LOCATION}; 
    ProcessBuilder processBuilder = new ProcessBuilder(command); 

    Process process = processBuilder.start(); 
    /** 
    * Check if any errors or compilation errors encounter then print on Console. 
    */ 

    if(process.getErrorStream().read() != -1){ 
     print("Compilation Errors",process.getErrorStream()); 
    } 
    /** 
    * Check if javac process execute successfully or Not 
    * 0 - successful 
    */ 
    if(process.exitValue() == 0){ 
     process = new ProcessBuilder(new String[]{"java","-cp","d:\\","Test"}).start(); 
     /** Check if RuntimeException or Errors encounter during execution then print errors on console 
     * Otherwise print Output 
     */ 
     if(process.getErrorStream().read() != -1){ 
      print("Errors ",process.getErrorStream()); 
     } 
     else{ 
      print("Output ",process.getInputStream()); 
     } 

    } 
} 

private static void print(String status,InputStream input) throws IOException{ 
    BufferedReader in = new BufferedReader(new InputStreamReader(input)); 
    System.out.println("************* "+status+"***********************"); 
    String line = null; 
    while((line = in.readLine()) != null){ 
     System.out.println(line); 
    } 
    in.close(); 
} 

}

1

我能看到有比Apache的百科全書EXEC庫更好庫。 您可以使用Java Secure Shell(JSch)執行您的作業。

我有同樣的問題。我用JSch來解決這個問題。 Apache commons在不同服務器上運行命令時遇到了一些問題。 Plus JSch給了我結果和錯誤InputStreams。我發現它更優雅。樣品溶液可以在這裏找到:http://wiki.jsch.org/index.php?Manual%2FExamples%2FJschExecExample

import java.io.InputStream; 
    import java.io.BufferedReader; 
    import java.io.InputStreamReader; 

    import org.apache.commons.exec.*; 

    import com.jcraft.*; 
    import com.jcraft.jsch.JSch; 
    import com.jcraft.jsch.Session; 
    import com.jcraft.jsch.ChannelExec; 

    import java.util.Arrays; 
    import java.util.List; 
    import java.util.ArrayList; 
    import java.util.HashMap; 


    public class exec_linux_cmd { 
     public HashMap<String,List<String>> exec_cmd (
       String USERNAME, 
       String PASSWORD, 
       String host, 
       int port, 
       String cmd) 
     { 
      List<String> result = new ArrayList<String>(); 
      List<String> errors = new ArrayList<String>(); 
      HashMap<String,List<String>> result_map = new HashMap<String,List<String>>(); 
     //String line = "echo `eval hostname`"; 
      try{ 
      JSch jsch = new JSch(); 
      /* 
      * Open a new session, with your username, host and port 
      * Set the password and call connect. 
      * session.connect() opens a new connection to remote SSH server. 
      * Once the connection is established, you can initiate a new channel. 
      * this channel is needed to connect and remotely execute the program 
      */ 

      Session session = jsch.getSession(USERNAME, host, port); 
      session.setConfig("StrictHostKeyChecking", "no"); 
      session.setPassword(PASSWORD); 
      session.connect(); 

      //create the excution channel over the session 
      ChannelExec channelExec = (ChannelExec)session.openChannel("exec"); 

      // Gets an InputStream for this channel. All data arriving in as messages from the remote side can be read from this stream. 
      InputStream in = channelExec.getInputStream(); 
      InputStream err = channelExec.getErrStream(); 

      // Set the command that you want to execute 
      // In our case its the remote shell script 

      channelExec.setCommand(cmd); 

      //Execute the command 
      channelExec.connect(); 

      // read the results stream 
      BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 
      // read the errors stream. This will be null if no error occured 
      BufferedReader err_reader = new BufferedReader(new InputStreamReader(err)); 
      String line; 

      //Read each line from the buffered reader and add it to result list 
      // You can also simple print the result here 

      while ((line = reader.readLine()) != null) 
      { 
       result.add(line); 
      } 

      while ((line = err_reader.readLine()) != null) 
      { 
       errors.add(line); 
      } 

      //retrieve the exit status of the remote command corresponding to this channel 
      int exitStatus = channelExec.getExitStatus(); 
      System.out.println(exitStatus); 

      //Safely disconnect channel and disconnect session. If not done then it may cause resource leak 
      channelExec.disconnect(); 
      session.disconnect(); 
      System.out.println(exitStatus); 
      result_map.put("result", result); 
      result_map.put("error", errors); 

      if(exitStatus < 0){ 
       System.out.println("Done--> " + exitStatus); 
       System.out.println(Arrays.asList(result_map)); 
       //return errors; 
      } 
      else if(exitStatus > 0){ 
       System.out.println("Done -->" + exitStatus); 
       System.out.println(Arrays.asList(result_map)); 
       //return errors; 
      } 
      else{ 
       System.out.println("Done!"); 
       System.out.println(Arrays.asList(result_map)); 
       //return result; 
      } 

      } 
      catch (Exception e) 
      { 
       System.out.print(e); 
      } 

      return result_map; 
     } 



     //CommandLine commandLine = CommandLine.parse(cmd); 
     //DefaultExecutor executor = new DefaultExecutor(); 
     //executor.setExitValue(1); 
     //int exitValue = executor.execute(commandLine); 

      public static void main(String[] args) 
      { 
       //String line = args[0]; 
       final String USERNAME ="abc"; // username for remote host 
       final String PASSWORD ="abc"; // password of the remote host 
       final String host = "3.98.22.10"; // remote host address 
       final int port=22; // remote host port 
       HashMap<String,List<String>> result = new HashMap<String,List<String>>(); 

       //String cmd = "echo `eval hostname`"; // command to execute on remote host 
       exec_linux_cmd ex = new exec_linux_cmd(); 

       result = ex.exec_cmd(USERNAME, PASSWORD , host, port, cmd); 
       System.out.println("Result ---> " + result.get("result")); 
       System.out.println("Error Msg ---> " +result.get("error")); 
       //System.out.println(Arrays.asList(result)); 

       /* 
       for (int i =0; i < result.get("result").size();i++) 
       { 
         System.out.println(result.get("result").get(i)); 
       } 
       */ 

      } 
    } 

編輯1:爲了找到你的進程(如果它是一個長期運行的一個)是在Unix上運行,使用ps -aux | grep java。進程ID應與您正在執行的unix命令一起列出。