Java ProcessBuilder
last modified July 12, 2024
In this article we show how to create operating system processes with
ProcessBuilder
.
ProcessBuilder is used to create operating system processes.
Its start
method creates a new Process
instance
with the following attributes:
- command
- environment
- working directory
- source of input
- destination for standard output and standard error output
- redirectErrorStream
Running a program
A program is executed with command
. With waitFor
we can wait for the process to finish.
import java.io.IOException; void main() throws IOException, InterruptedException { var processBuilder = new ProcessBuilder(); processBuilder.command("notepad.exe"); var process = processBuilder.start(); var ret = process.waitFor(); System.out.printf("Program exited with code: %d", ret); }
The program executes the Windows Notepad application. It returns its exit code.
Command output
The following example executes a command and shows its output.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; void main() throws IOException { var processBuilder = new ProcessBuilder(); processBuilder.command("cal", "2022", "-m 2"); var process = processBuilder.start(); try (var reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } }
The example runs Linux cal
command.
processBuilder.command("cal", "2022", "-m 2");
The command
executes the cal
program. The other
parameters are the options of the program. In order to run a command on Windows
machine, we could use the following: processBuilder.command("cmd.exe", "/c", "ping -n 3 google.com")
.
var process = processBuilder.start();
The process is lauched with start
.
try (var reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) {
With the getInputStream
method we get the input stream
from the standard output of the process.
$ java Main.java Február 2022 Ne Po Ut St Št Pi So 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
Redirecting output
With redirectOutput
, we can redirect the process builder's standard
output destination.
import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; void main() throws IOException { var homeDir = System.getProperty("user.home"); var processBuilder = new ProcessBuilder(); processBuilder.command("date"); var fileName = new File(String.format("%s/Documents/output.txt", homeDir)); processBuilder.redirectOutput(fileName); var process = processBuilder.start(); try (var reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } }
The program redirects the builder's output to a file. It runs the Windows
date
command.
processBuilder.redirectOutput(fileName);
We redirect the process builders standard output to a file.
try (var reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } }
Now the output goes to the file.
$ java Main.java $ cat ~/Documents/output.txt Tue, Feb 20, 2024 10:18:11 PM
The current date was written to the output.txt
file.
Redirecting input and output
The next example redirects both input and output.
sky blue steel morning coffee earth forest
This are the contents of the input.txt
file.
import java.io.File; import java.io.IOException; void main() throws IOException { var processBuilder = new ProcessBuilder(); processBuilder.command("cat") .redirectInput(new File(".", "input.txt")) .redirectOutput(new File(".", "output.txt")).start(); }
In the program, we redirect input from an input.txt
file to the
cat
command and redirect the command's output to the output.txt
file.
The inheritIO method
The inheritIO
sets the source and destination for subprocess
standard I/O to be the same as those of the current Java process.
import java.io.IOException; void main() throws IOException, InterruptedException { var processBuilder = new ProcessBuilder(); processBuilder.command("cmd.exe", "/c", "dir"); var process = processBuilder.inheritIO().start(); int exitCode = process.waitFor(); System.out.printf("Program ended with exitCode %d", exitCode); }
By inheriting the IO of the executed command, we can skip the reading step. The program outputs the contents of the project directory and the message showing the exit code.
$ java Main.java Directory of C:\Users\Jano\Documents\prog\java\simple 20. 02. 2024 22:25 <DIR> . 20. 02. 2024 21:45 <DIR> .. 20. 02. 2024 22:23 357 Main.java 1 File(s) 357 bytes 2 Dir(s) 34 407 276 544 bytes free Program ended with exitCode 0
We get both the output of the executed command and of our own Java program.
The environment method
The environment
method returns a string map view of
the process builder's environment.
void main() { var pb = new ProcessBuilder(); var env = pb.environment(); env.forEach((s, s2) -> System.out.printf("%s %s %n", s, s2)); System.out.printf("%s %n", env.get("PATH")); }
The program shows all environment variables.
$ java Main.java configsetroot C:\WINDOWS\ConfigSetRoot USERDOMAIN_ROAMINGPROFILE LAPTOP-OBKOFV9J LOCALAPPDATA C:\Users\Jano\AppData\Local PROCESSOR_LEVEL 6 USERDOMAIN LAPTOP-OBKOFV9J LOGONSERVER \\LAPTOP-OBKOFV9J JAVA_HOME C:\Users\Jano\.jdks\jdk21.0.2_13 SESSIONNAME Console ...
This is a sample output on Windows.
In the next program, we define a custom environment variable.
import java.io.IOException; void main() throws IOException { var pb = new ProcessBuilder(); var env = pb.environment(); env.put("mode", "development"); pb.command("cmd.exe", "/c", "echo", "%mode%"); pb.inheritIO().start(); }
The program defines a mode
variable and outputs it on
Windows.
pb.command("cmd.exe", "/c", "echo", "%mode%");
The %mode%
is a Windows syntax for environment variables;
on Linux we use $mode
.
The directory method
The directory
method sets the process builder's working directory.
import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; void main() throws IOException { var homeDir = System.getProperty("user.home"); var pb = new ProcessBuilder(); pb.command("cmd.exe", "/c", "dir"); pb.directory(new File(homeDir)); var process = pb.start(); try (var reader = new BufferedReader( new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } }
The example sets the home directory to be the process builder's current directory. We show the contents of the home directory.
var homeDir = System.getProperty("user.home");
We get the user's home directory.
pb.command("cmd.exe", "/c", "dir");
We define a command which executes the dir
program on Windows.
pb.directory(new File(homeDir));
We set the process builder's directory.
$ java Main.java Volume in drive C is Windows Volume Serial Number is 4415-13BB Directory of C:\Users\Jano 02/14/2019 11:48 AM <DIR> . 02/14/2019 11:48 AM <DIR> .. 10/13/2018 08:38 AM <DIR> .android 01/31/2019 10:58 PM 281 .bash_history 12/17/2018 03:02 PM <DIR> .config ...
Non-blocking operations
In the following example, we create a process which is asynchronous.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; void main() throws InterruptedException, ExecutionException, TimeoutException, IOException { try (var executor = Executors.newSingleThreadExecutor()) { var processBuilder = new ProcessBuilder(); processBuilder.command("cmd.exe", "/c", "ping -n 3 google.com"); try { var process = processBuilder.start(); System.out.println("processing ping command ..."); var task = new ProcessTask(process.getInputStream()); Future<List<String>> future = executor.submit(task); // non-blocking, doing other tasks System.out.println("doing task1 ..."); System.out.println("doing task2 ..."); var results = future.get(5, TimeUnit.SECONDS); for (String res : results) { System.out.println(res); } } finally { executor.shutdown(); } } } class ProcessTask implements Callable<List<String>> { private final InputStream inputStream; public ProcessTask(InputStream inputStream) { this.inputStream = inputStream; } @Override public List<String> call() { return new BufferedReader(new InputStreamReader(inputStream)) .lines() .collect(Collectors.toList()); } }
The program creates a process that runs the ping command on the console.
It is executed in a separate thread with the help of the
Executors.newSingleThreadExecutor
method.
$ java Main.java processing ping command ... doing task1 ... doing task2 ... Pinging google.com [2a00:1450:4001:825::200e] with 32 bytes of data: Reply from 2a00:1450:4001:825::200e: time=108ms Reply from 2a00:1450:4001:825::200e: time=111ms Reply from 2a00:1450:4001:825::200e: time=112ms Ping statistics for 2a00:1450:4001:825::200e: Packets: Sent = 3, Received = 3, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 108ms, Maximum = 112ms, Average = 110ms
The pipe operation
A pipe is a technique for passing information from one program process to another.
import java.io.File; import java.io.IOException; void main() throws IOException { var homeDir = System.getProperty("user.home"); var processBuilder = new ProcessBuilder(); processBuilder.command("cmd.exe", "/c", "dir | grep [dD]o"); processBuilder.directory(new File(homeDir)); processBuilder.inheritIO().start(); }
The example sends information from a dir
commmand to the grep
command through the pipe (|).
$ java Main.java Volume in drive C is Windows 11/14/2018 06:57 PM <DIR> .dotnet 02/18/2019 10:54 PM <DIR> Documents 02/17/2019 01:11 AM <DIR> Downloads
Source
Java ProcessBuilder - language reference
In this article we have used Java's ProcessBuilder
to execute OS processes.
Author
List all Java tutorials.