A Beginner's Guide to ProcessBuilder in Java
Understanding and Implementing System Proccesses
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.