Выполнение другого приложения из Java - PullRequest
17 голосов
/ 12 августа 2010

Мне нужно выполнить командный файл, который выполняет другое приложение Java. Мне все равно, успешно он выполняется или нет, и мне не нужно фиксировать какие-либо ошибки.

Возможно ли это сделать с ProcessBuilder ? Каковы последствия, если я не фиксирую ошибки?

Однако мое требование - просто выполнить другое приложение Java.

Ответы [ 10 ]

29 голосов
/ 12 августа 2010

Подход 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);
25 голосов
/ 12 августа 2010

Да, это возможно с помощью 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-се-советы / java.util / из-Runtime.exec к processbuilder.html

4 голосов
/ 06 ноября 2012

Вот пример того, как использовать 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() будет ожидать завершения процесса, прежде чем продолжить.Этот метод возвращает код ошибки процесса, но, поскольку вы не заботитесь об этом, я не поместил его в пример.

4 голосов
/ 12 августа 2010

Вы можете выполнить пакетную инструкцию или любое другое приложение, используя

Runtime.getRuntime().exec(cmd);
  • cmd - это команда или путь к приложению.

Также вы можете подождатьвыполнение и получение кода возврата (чтобы проверить, правильно ли он выполнен) с этим кодом:

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

У вас есть полное объяснение различных типов вызовов здесь http://www.rgagnon.com/javadetails/java-0014.html

4 голосов
/ 12 августа 2010

Я предполагаю, что вы знаете, как выполнить команду, используя ProcessBuilder.

Выполнение команды из Java всегда должно считывать потоки stdout и stderr из процесса.В противном случае может случиться так, что буфер заполнен, и процесс не может продолжаться из-за записи его блоков stdout или stderr.

2 голосов
/ 29 января 2016

Ниже приведен фрагмент кода для компиляции и запуска внешней JAVA-программы с использованием ProcessBuilder, аналогично тому, как мы можем запускать любую внешнюю программу.Убедитесь, что JAVA_HOME должен быть установлен в среде ОС.см подробнее

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

}

2 голосов
/ 20 июня 2014

Я знаю, что это более старый поток, но я полагаю, что было бы целесообразно включить его в мою реализацию, так как я обнаружил, что этот поток пытается сделать то же самое, что и OP, за исключением доступа с корневым уровнем, но в действительностинайти решение, которое я искал.Приведенный ниже метод создает статическую оболочку корневого уровня, которая используется только для выполнения команд, независимо от проверки ошибок или даже если команда выполнена успешно.

Я использую созданное мной приложение для фонарика Android, которое позволяет настраивать светодиод на другой уровень яркости.Удалив все проверки ошибок и другой пух, я могу заставить светодиод переключаться на заданный уровень яркости всего за 3 мсек, что открывает дверь в LightTones (звонки со светом).Более подробную информацию о самом приложении можно найти здесь: 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;
    }
}

Затем в любом месте моего приложения для запуска команды, например, изменения яркости светодиода, я просто вызываю:

Shell.exec("echo " + bt.getLevel() + " > "+ flashfile);
1 голос
/ 18 апреля 2017

Я мог видеть, что есть лучшая библиотека, чем библиотека apache commons exec. Вы можете выполнить свою работу, используя Java Secure Shell (JSch).

У меня была такая же проблема. Я использовал JSch для решения этой проблемы. У Apache commons были некоторые проблемы с запуском команд на другом сервере. Плюс 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. Идентификатор процесса должен быть указан вместе с выполняемой вами командой unix.

1 голос
/ 12 августа 2010

Если вас не волнует возвращаемое значение, вы можете просто использовать Runtime.getRuntime().exec("path.to.your.batch.file");

0 голосов
/ 12 августа 2010

Вы можете просто использовать Runtime.exec ()

...