2010-08-12 36 views
14

Necesito ejecutar un archivo por lotes que ejecute otra aplicación Java. No me importa si se ejecuta correctamente o no y no tengo que capturar ningún error.Ejecutando otra aplicación desde Java

¿Es posible hacer esto con ProcessBuilder? ¿Cuáles son las consecuencias si no capturo los errores?

Sin embargo, mi requisito es simplemente ejecutar otra aplicación Java.

Respuesta

4

Supongo que sabe cómo ejecutar el comando usando el ProcessBuilder.

La ejecución de un comando desde Java siempre debe leer las secuencias stdout y stderr del proceso. De lo contrario, puede suceder que el búfer esté lleno y el proceso no pueda continuar porque escribe sus bloques stdout o stderr.

+0

¿Hay alguna manera de simplemente iniciar la otra aplicación e ignorar las corrientes stdout y stderr del proceso? – user234194

+0

Quizás crees un archivo 'bat' que redirige la salida del comando ejecutado a" dev-null ". – Mot

1

Si no se preocupan por el valor de retorno es posible que utilices Runtime.getRuntime().exec("path.to.your.batch.file");

+0

qué pasa con las corrientes stdout y stderr a partir del proceso completo. – user234194

+0

Sin saber lo que quiere ejecutar, es un poco difícil de decir. He visto programas como el BCP de SQL Server que no informan los errores correctamente cuando se ejecutan y solicitan las transmisiones stdout y stderr, por lo que depende del proceso de su hijo. Si no tiene ningún resultado, entonces no se preocupe, stdr y stderr serán recolectados junto con su objeto 'Process' cuando el proceso haya finalizado –

+0

Tengo una pregunta simple, ¿qué pasa si tan pronto como ejecutar otra aplicación java, no puedo hacer process.destroy. ¿Eso no ayuda a que se complete o se complique, o estoy hablando de cosas totalmente diferentes? Porque, una vez que se inicia la otra aplicación, puedo salir de mi aplicación. – user234194

29

El enfoque Runtime.getRuntime().exec() es bastante molesto, ya que encontrará en breve.

Eche un vistazo al proyecto Apache Commons Exec. Se abstrae de muchos de los problemas comunes asociados con el uso de la API Runtime.getRuntime().exec() y ProcessBuilder.

Es tan simple como:

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

esta respuesta me salvó vida. Gracias – Valath

4

Puede ejecutar una instrucción de proceso por lotes, o cualquier otra aplicación que utilice

Runtime.getRuntime().exec(cmd); 
  • cmd es el comando o Te ruta de la aplicación.

También yo puedo esperar para ejecutar y obtener el código de retorno (para comprobar si su correcta ejecución) con este código:

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

Usted tiene una explicación completa de diferentes tipos de llamadas aquí http://www.rgagnon.com/javadetails/java-0014.html

+4

Process.waitFor() en realidad devuelve el código de salida del proceso, por lo que podría combinar las dos últimas líneas a "int.exitVal = p.waitFor();" –

22

Sí, es posible usar ProcessBuilder.

ejemplo 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!"); 
    } 
} 

comprobar estos ejemplos:

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

Excepción en el hilo "principal" java.lang.ArrayIndexOutOfBoundsException: 0 \t en RunClByJava.main (RunClByJava.java:94) –

4

Aquí está un ejemplo de cómo utilizar ProcessBuilder para ejecutar su aplicación remota.Ya que no se preocupan de entrada/salida y/o errores, puede hacerlo de la siguiente manera:

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(); 

el método waitFor() esperará hasta que el proceso había terminado antes de continuar. Este método devuelve el código de error del proceso pero, como no te importa, no lo puse en el ejemplo.

2

Sé que este es un hilo más antiguo, pero creo que valdría la pena implementarlo ya que encontré este hilo tratando de hacer lo mismo que OP, excepto con el acceso de nivel Root, pero no lo hice realmente encontrar una solución que estaba buscando. El siguiente método crea un shell de nivel de Root estático que se utiliza para ejecutar comandos sin tener en cuenta la comprobación de errores o incluso si el comando se ejecutó correctamente.

Lo uso una aplicación de linterna de Android que he creado que permite configurar el LED a diferentes niveles de brillo. Al eliminar todas las comprobaciones de errores y demás pelusas, puedo hacer que el LED cambie a un nivel de brillo específico en tan solo 3 ms, lo que abre la puerta a LightTones (RingTones con luz). Puede encontrar más detalles sobre la aplicación aquí: http://forum.xda-developers.com/showthread.php?t=2659842

A continuación se detalla la clase en su totalidad.

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; 
    } 
} 

A continuación, en cualquier lugar en mi aplicación para ejecutar un comando, para cambiar el brillo del LED ejemplo, acabo de llamar:

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

A continuación fragmento de código está escrito para compilar y ejecutar programas Java externo utilizando ProcessBuilder, De la misma manera que podemos ejecutar cualquier programa externo. Asegúrese de que JAVA_HOME se configure en el entorno del sistema operativo. ver 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

pude ver que hay una biblioteca mejor que los comunes librería Apache Exec. Puede ejecutar su trabajo utilizando Java Secure Shell (JSch).

Tuve el mismo problema. Usé JSch para resolver este problema. Los comunes de Apache tenían algunos problemas al ejecutar comandos en un servidor diferente. Además JSch me dio resultados y errores InputStreams. Lo encontré más elegante. solución de la muestra se puede encontrar aquí: 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)); 
       } 
       */ 

      } 
    } 

EDIT 1: Con el fin de encontrar su proceso (si es una larga uno) que se está ejecutando en Unix, utilice el ps -aux | grep java. La ID del proceso debe aparecer junto con el comando Unix que está ejecutando.

Cuestiones relacionadas