A Beginner's Guide to ProcessBuilder in Java

A Beginner's Guide to ProcessBuilder in Java

Understanding and Implementing System Proccesses

ยท

4 min read

Introduction

ProcessBuilder is a class in Java that enables developers to start and manage operating system processes from within their Java applications. This can be useful for executing shell commands, scripts or other applications from your Java code. With the help of the ProcessBuilder class, you can execute a command, redirect its input and output streams, and even wait for its completion.

Why use ProcessBuilder?

The ProcessBuilder class offers an easy way to execute shell commands or scripts from within Java code. It can be especially useful for developers who want to automate tasks or manipulate the operating system from within their Java applications. For instance, you can use ProcessBuilder to execute shell commands that run backups, install packages or perform other tasks that are typically performed in the command line.

Now let's see how we can create a Process using Java.

To create a new process builder with the specified operating system program and arguments, we can use this convenient constructor

ProcessBuilder(String... command)

Creating a Process

The ProcessBuilder class provides several methods to create a new process. The most basic method is to use the start() method, which takes an array of strings as input. This array represents the command that you want to execute, along with any arguments.

Here is an example of using the start() method:

ProcessBuilder pb = new ProcessBuilder("java", "-version");
Process process = pb.start();

In this example, the command "java -version" is passed as an array of strings to the ProcessBuilder constructor. The start() method is then used to start the process.

Redirecting Standard Input and Output

In the real world, we will probably want to capture the results of our running processes inside a log file for further analysis. Luckily the ProcessBuilder API has built-in support for exactly this as we will see in this example

By default, the input and output streams of a process are connected to the parent process. This means that if you print to the standard output, it will be sent to the parent process, and if you read from the standard input, you will receive data from the parent process.

Let's return to our original example to print out the version of Java. But this time let's redirect the output to a log file instead of the standard output.

ProcessBuilder processBuilder = new ProcessBuilder("java", "-version");

processBuilder.redirectErrorStream(true);
File log = folder.newFile("java-version.log");
processBuilder.redirectOutput(log);

Process process = processBuilder.start();

In the above example, we create a new temporary file called log and tell our ProcessBuilder to redirect output to this file destination

Waiting for Completion

The start() method returns immediately, allowing you to continue executing other tasks while the process is running. To wait for the process to complete, you can use the waitFor() method.

Here is an example of waiting for a process to complete:

ProcessBuilder pb = new ProcessBuilder("java", "-version");
Process process = pb.start();
int exitCode = process.waitFor();

In this example, the waitFor() method is used to wait for the process to complete. Once the process has been completed, the exitCode variable will contain the exit code of the process. If the exitCode will 0 then the process successfully completed.

How do get the Process ID (PID) of the command

In a Unix-like or Linux operating system, each process is identified by a unique numeric identifier called the Process ID or PID. In some situations, we may need to obtain the PID of a running process programmatically. Here we will explore a different way to get the PID of the command.

Using pgrep command only work in linux

One way to get the PID of a command is by using the pgrep command. This command returns the PID of the processes matching a pattern. We can use the -f option to search for a process by its command name.

String command = "some command";
String processcmd = "pgrep -f " + command; // pass command with pgrep -f
String processId = "";

ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash", "-c", processcmd);
Process result = processBuilder.start(); //start() will run the command
BufferedReader reader = new BufferedReader(new InputStreamReader(result.getInputStream())); // reading the output of the command
List<String> pid = reader.lines().collect(Collectors.toList()); // collect the line in list
if (!pid.isEmpty()) {
    processId = pid.get(0); // get the pid at first position
    System.out.println(String.format("Process ID for command '%s' is %s", command, processId));
    } else {
        System.out.println(String.format("No process found for command '%s'", command));
        }
    }

The pgrep -f command searches for a process by its command name. The output of the pgrep command is captured using the java.io.BufferedReader method of the String class, which returns the output of the command as a String and java.util.stream.Collectors has been used for reading the input stream and collecting line respectely in List variable pid. PID at the first position will be the pid of the command.

Conclusion:

The ProcessBuilder class provides a convenient way to execute shell commands and manage operating system processes from within Java code. With the help of this class, you can redirect input and output streams, wait for completion, and even manipulate the environment of a process. Whether you are automating tasks or integrating with other applications, the ProcessBuilder class can help you get the job done.

Did you find this article valuable?

Support Krishna Kumar by becoming a sponsor. Any amount is appreciated!

ย