Java ProcessBuilder examples
In Java, we can use ProcessBuilder
to call external commands easily :
ProcessBuilder processBuilder = new ProcessBuilder();
// -- Linux --
// Run a shell command
processBuilder.command("bash", "-c", "ls /home/mkyong/");
// Run a shell script
processBuilder.command("path/to/hello.sh");
// -- Windows --
// Run a command
processBuilder.command("cmd.exe", "/c", "dir C:\\Users\\mkyong");
// Run a bat file
processBuilder.command("C:\\Users\\mkyong\\hello.bat");
Process process = processBuilder.start();
1. Ping
1.1 Run an external ping command to ping a website 3 times, and display the output.
ProcessBuilderExample1.java
package com.mkyong.process;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ProcessBuilderExample1 {
public static void main(String[] args) {
ProcessBuilder processBuilder = new ProcessBuilder();
// Run this on Windows, cmd, /c = terminate after this run
processBuilder.command("cmd.exe", "/c", "ping -n 3 google.com");
try {
Process process = processBuilder.start();
// blocked :(
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Output
Pinging google.com [172.217.166.142] with 32 bytes of data:
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55
Ping statistics for 172.217.166.142:
Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 10ms, Maximum = 10ms, Average = 10ms
Exited with error code : 0
2. Ping + Thread
In above example 1.1, the process.getInputStream
is “blocking”, it is better to start a new Thread for the reading process, so that it won’t block other tasks.
ProcessBuilderExample2.java
package com.mkyong.process;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
public class ProcessBuilderExample2 {
public static void main(String[] args) {
ExecutorService pool = Executors.newSingleThreadExecutor();
ProcessBuilder processBuilder = new ProcessBuilder();
// Run this on Windows, cmd, /c = terminate after this run
processBuilder.command("cmd.exe", "/c", "ping -n 3 google.com");
try {
Process process = processBuilder.start();
System.out.println("process ping...");
ProcessReadTask task = new ProcessReadTask(process.getInputStream());
Future<list<string>> future = pool.submit(task);
// no block, can do other tasks here
System.out.println("process task1...");
System.out.println("process task2...");
List<string> result = future.get(5, TimeUnit.SECONDS);
for (String s : result) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
pool.shutdown();
}
}
private static class ProcessReadTask implements Callable<list<string>> {
private InputStream inputStream;
public ProcessReadTask(InputStream inputStream) {
this.inputStream = inputStream;
}
@Override
public List<string> call() {
return new BufferedReader(new InputStreamReader(inputStream))
.lines()
.collect(Collectors.toList());
}
}
}
Output
process ping...
process task1...
process task2...
Pinging google.com [172.217.166.142] with 32 bytes of data:
Reply from 172.217.166.142: bytes=32 time=11ms TTL=55
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55
Reply from 172.217.166.142: bytes=32 time=10ms TTL=55
Ping statistics for 172.217.166.142:
Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 10ms, Maximum = 11ms, Average = 10ms
3. Change Directory
3.1 Change to directory C:\\users
and run external dir
command to list out all the files.
ProcessBuilderExample3.java
package com.mkyong.process;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class ProcessBuilderExample3 {
public static void main(String[] args) {
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command("cmd.exe", "/c", "dir");
processBuilder.directory(new File("C:\\users"));
// can also run the java file like this
// processBuilder.command("java", "Hello");
try {
Process process = processBuilder.start();
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Output
Volume in drive C has no label.
Volume Serial Number is CE5B-B4C5
Directory of C:\users
//...
Hi:
Thanks so much for you helpful post:)
May I ask several questions:
Thanks again 🙂
Hi,
could you please let me know if there is an existing OpenSource Java library which creates OS based tasks (task scheduler on windows, crontab on linux), reads the task execution history ?
something similar to this Java API (this is not a finished project)
https://github.com/martinodutto/windows-task-scheduler-api
Thanks,
Charan
Hello,
How can combine dos commands with Linux commands?
So, I need to run git-bash command and then a Linux command and to store the result into a file.
Hi, I have some questions .I have written a shell script which connects to oracle database and performs operation and returns some output message. Script works fine from command prompt.
But my problem is , the shell script takes nearly 1 hour or less or even more to do its job in the database and untill then my console keeps showing as busy. Whereas in command prompt, shell script displays messages as it runs and thus keeps the end user informed about its progress. However, when called from java it waits untill the shell script completes/terminates and finally displays all the messages at once. I want to know if there is a way to display the shell script output as it continues to run in the background ( child process ).
hi, Can we execute kubectl commands through java?
Very useful. You do have the odd mistake. list -> List or string -> String. But helped me a great deal. Cheers
How i update a file in linux
in linux use vi filename-> press key i-> go to the line where modification is required -> update the value -> esc -> :wq
how to do these commands in java and how to go to the particular line which needs modification?
In Eclipse, I get an error with the code below. Type mismatch: cannot convert from List to List
@Override
public List call() {
return new BufferedReader(new InputStreamReader(inputStream))
.lines()
.collect(Collectors.toList());
}
how to run a batch file with arguments using ProcessBuilder
Minor typo in code: <list> should be <List>