Java execute process example

Руководство по java.lang.Process API

В этом руководстве мы возьмемan in-depth look at the Process API.

Для более подробного изучения того, как использоватьProcess для выполнения команды оболочки, мы можем обратиться к нашему предыдущему руководствуhere.

Процесс, к которому он относится, является исполняемым приложением. КлассProcess предоставляет методы для взаимодействия с этими процессами, включая извлечение вывода, выполнение ввода, мониторинг жизненного цикла, проверку статуса выхода и его уничтожение (уничтожение).

2. Использование классаProcess для компиляции и запуска Java-программы

Давайте посмотрим на пример компиляции и запуска другой программы Java с помощью APIProcess:

@Test public void whenExecutedFromAnotherProgram_thenSourceProgramOutput3() throws IOException < Process process = Runtime.getRuntime() .exec("javac -cp src src\\main\\java\\com\\example\\java9\\process\\OutputStreamExample.java"); process = Runtime.getRuntime() .exec("java -cp src/main/java com.example.java9.process.OutputStreamExample"); BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream())); int value = Integer.parseInt(output.readLine()); assertEquals(3, value); >

Таким образом, приложения для выполнения кода Java в существующем коде Java практически безграничны.

3. Создание процесса

Наше Java-приложение может вызывать любое приложение, которое работает в нашей компьютерной системе, в зависимости от ограничений операционной системы.

Поэтому мы можем выполнять приложения. Давайте посмотрим, какие варианты использования мы можем запустить с помощью Process API.

КлассProcessBuilder позволяет нам создавать подпроцессы в нашем приложении.

Давайте посмотрим на демонстрацию открытия приложения Блокнот для Windows:

ProcessBuilder builder = new ProcessBuilder("notepad.exe"); Process process = builder.start();

4. Уничтожающий процесс

Process также предоставляет нам методы для уничтожения подпроцессов или процессов. Although, how the application is killed is platform-dependent.

Давайте посмотрим на возможные варианты использования.

4.1. Уничтожение процесса по ссылке

Допустим, мы используем ОС Windows и хотим создать приложение «Блокнот» и уничтожить его.

Как и раньше, мы можем создать экземпляр приложения «Блокнот», используя классProcessBuilder и методstart().

Затем мы можем вызвать методdestroy() для нашего объектаProcess.

4.2. Уничтожение процесса по идентификатору

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

Caution should be advised while doing this, as we can unknowingly destroy a critical process which might make the operating system unstable.

Сначала нам нужно узнать идентификатор текущего запущенного процесса, проверив диспетчер задач и выяснив pid.

Давайте посмотрим на пример:

Optional optionalProcessHandle = ProcessHandle.of(5232); optionalProcessHandle.ifPresent(processHandle -> processHandle.destroy());

4.3. Разрушение процесса силой

При выполнении методаdestroy() подпроцесс будет остановлен, как мы видели ранее в статье.

Читайте также:  All about python programming language

В случае, когдаdestroy() не работает, у нас есть опцияdestroyForcibly().

Мы всегда должны начинать с методаdestroy(). После этого мы можем выполнить быструю проверку подпроцесса, выполнивisAlive().

Если он вернет истину, выполнитеdestroyForcibly():

ProcessBuilder builder = new ProcessBuilder("notepad.exe"); Process process = builder.start(); process.destroy(); if (process.isAlive())

5. Ожидание завершения процесса

У нас также есть два перегруженных метода, с помощью которых мы можем обеспечить ожидание завершения процесса.

5.1. waitfor()с

Когда этот метод выполняется, он помещаетthe current execution process thread in a blocking-wait state unless the sub-process gets terminated.

Давайте посмотрим на пример:

ProcessBuilder builder = new ProcessBuilder("notepad.exe"); Process process = builder.start(); assertThat(process.waitFor() >= 0);

Из приведенного выше примера видно, что текущий поток продолжает выполнение, он будет продолжать ждать окончания потока подпроцесса. Как только подпроцесс завершится, текущий поток продолжит свое выполнение.

5.2. waitfor(long timeOut, TimeUnit time)с

Когда этот метод выполняется, он помещаетthe current execution process thread in the blocking-wait state unless the sub-process gets terminated or runs out of time.

Давайте посмотрим на пример:

ProcessBuilder builder = new ProcessBuilder("notepad.exe"); Process process = builder.start(); assertFalse(process.waitFor(1, TimeUnit.SECONDS));

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

Когда этот метод выполняется, он возвращает логическое значение true, если подпроцесс завершился, или логическое значение false, если время ожидания истекло до выхода из подпроцесса.

6. exitValue()с

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

Another way around if the subprocess has been successfully terminated then it will result in an exit value of the process.

Это может быть любое возможное положительное целое число.

Давайте посмотрим на пример, когда методexitValue() возвращает положительное целое число, когда подпроцесс был успешно завершен:

@Test public void givenSubProcess_whenCurrentThreadWillNotWaitIndefinitelyforSubProcessToEnd_thenProcessExitValueReturnsGrt0() throws IOException < ProcessBuilder builder = new ProcessBuilder("notepad.exe"); Process process = builder.start(); assertThat(process.exitValue() >= 0); >

7. isAlive()с

Когда мы хотим выполнить бизнес-обработку, которая является субъективной, независимо от того, работает процесс или нет.

Мы можем выполнить быструю проверку, чтобы определить, активен ли процесс или нет, который возвращает логическое значение.

Давайте посмотрим на небольшой пример:

ProcessBuilder builder = new ProcessBuilder("notepad.exe"); Process process = builder.start(); Thread.sleep(10000); process.destroy(); assertTrue(process.isAlive());

8. Обработка потоков процессов

По умолчанию созданный подпроцесс не имеет своего терминала или консоли. Все его стандартные операции ввода-вывода (т.е. операции stdin, stdout, stderr) будут отправлены родительскому процессу. Таким образом, родительский процесс может использовать эти потоки для подачи входных данных и получения выходных данных из подпроцесса.

Следовательно, это дает нам огромную гибкость, поскольку дает нам контроль над вводом / выводом нашего подпроцесса.

Читайте также:  Java create certificate keytool

8.1. getErrorStream()с

Интересно, что мы можем извлечь ошибки, сгенерированные из подпроцесса, и затем выполнить бизнес-обработку.

После этого мы можем выполнить определенные проверки бизнес-обработки на основе наших требований.

Давайте посмотрим на пример:

@Test public void givenSubProcess_whenEncounterError_thenErrorStreamNotNull() throws IOException

8.2. getInputStream()с

Мы также можем получить выходные данные, сгенерированные подпроцессом, и использовать их в родительском процессе, что позволяет обмениваться информацией между процессами:

@Test public void givenSourceProgram_whenReadingInputStream_thenFirstLineEquals3() throws IOException < Process process = Runtime.getRuntime().exec( "javac -cp src src\\main\\java\\com\\example\\java9\\process\\OutputStreamExample.java"); process = Runtime.getRuntime() .exec("java -cp src/main/java com.example.java9.process.OutputStreamExample"); BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream())); int value = Integer.parseInt(output.readLine()); assertEquals(3, value); >

8.3. getOutputStream()

Мы можем отправить входные данные подпроцессу из родительского процесса:

Writer w = new OutputStreamWriter(process.getOutputStream(), "UTF-8"); w.write("send to child\n");

8.4. Фильтрация потоков процессов

Это идеальный вариант использования для взаимодействия с выборочно запущенными процессами.

Process предоставляет нам возможность выборочно фильтровать запущенные процессы на основе определенного предиката.

После этого мы можем выполнить бизнес-операции на этом выборочном наборе процессов:

@Test public void givenRunningProcesses_whenFilterOnProcessIdRange_thenGetSelectedProcessPid() < assertThat(((int) ProcessHandle.allProcesses() .filter(ph ->(ph.pid() > 10000 && ph.pid() < 50000)) .count()) >0); >

9. Заключение

Process — мощный класс для взаимодействия на уровне операционной системы. Запуск команд терминала, а также запуск, мониторинг и уничтожение приложений.

Для получения дополнительной информации о Java 9 Process API ознакомьтесь с нашей статьейhere.

Как всегда, вы найдете источникиover on Github.

Источник

Java exec: Execute system processes with Java ProcessBuilder and Process (part 1)

I’ve been thinking about rewriting my old tutorial on how to execute system processes from a Java application for a while now (How to run system commands from Java applications), but it’s a topic that quickly becomes complicated if you want to do it right, so I kept postponing it until I could give it some quality time in a real-world project.

I’ve finally had an opportunity to test this in a real-world Java application on a current project, so while I’m still not finished with this, I thought I’d share what I’ve learned so far.

The Apache Java exec project

Before continuing to read this article, if you don’t care how things work, and you just want to execute a system command from a Java application, you may just want to take a look at the Apache exec project. While some of that code may be dated (it is JDK 1.3 compatible), it is the same code that is used by the Apache Ant project, and is not a «work in progress», as the code shown below admittedly is. (I will probably have a few releases of this in the coming weeks.)

However, if you’d like to be able to execute system commands with just a few additional classes, and you get a detailed explanation of how the classes work, I welcome you to keep reading .

Читайте также:  Java lang character source

Basic Java exec with the ProcessBuilder and Process classes

When you first look at using the Java ProcessBuilder and Process to run (exec) system commands, it looks very easy. Just construct a ProcessBuilder object, tell it to start, and assign the results to a Process object, and you’re done.

Unfortunately what appears to be very simple — and what works in the simplest case — is not something you want to do if your job depends on the results.

For instance, in their ProcessBuilder javadoc, Sun shows an example like this:

// Sun's ProcessBuilder and Process example ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2"); Map env = pb.environment(); env.put("VAR1", "myValue"); env.remove("OTHERVAR"); env.put("VAR2", env.get("VAR1") + "suffix"); pb.directory("myDir"); Process p = pb.start();

That’s a nice, simple example, and it may indeed let you execute a system command, but if you want to read the standard output and standard error from your command, or supply standard input to your command, you need a much more robust solution.

A more-complete Java ProcessBuilder and Process approach

I’m not going to discuss all the possible pitfalls that you can run into when executing a system command from a Java application. That topic was already covered nicely about 10 years ago in a JavaWorld article, and to say the least, the ProcessBuilder example shown above won’t work in many cases.

Instead of rehashing all those pitfalls again, what I’m going to do is share some code that I’m currently developing for a project where I execute system commands like ping , netstat , and lsof , and then read the output of those commands once they’ve finished executing.

Beginning with the end in mind, let’s assume that we want to run the following Unix/Linux command from within a Java application:

To run that command from a Java application using my new code, we’d first build and then exec the command like this:

// build my command as a list of strings List command = new ArrayList(); command.add("ls"); command.add("-l"); command.add("/var/tmp"); // execute my command SystemCommandExecutor commandExecutor = new SystemCommandExecutor(command); int result = commandExecutor.executeCommand(); // get the output from the command StringBuilder stdout = commandExecutor.getStandardOutputFromCommand(); StringBuilder stderr = commandExecutor.getStandardErrorFromCommand(); // print the output from the command System.out.println("STDOUT"); System.out.println(stdout); System.out.println("STDERR"); System.out.println(stderr);

As you can see, as a consumer of a class named SystemCommandExecutor (which I will share with you shortly), I think this is pretty simple, and also lets you get the standard output and standard error from the command you just executed. Using this class you can even execute command pipelines from Java (such as «ps aux | wc -l»), as well as sudo commands. But, first things first .

Источник

Оцените статью