Reputation: 9
I have a function to execute a system command:
public String cmd(String s) {
String out = "";
try {
Runtime run = Runtime.getRuntime();
Process pr = run.exec(s.split(" "));
pr.waitFor();
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = "";
while ((line=buf.readLine())!=null) {
out+=line+"\n";
}
} catch(Exception e) {
e.printStackTrace();
}
return out;
}
The command passes through:
cmd("nmap -sL -n 192.168.1.0/24 | awk '/Nmap scan report/{print $NF}'");
Expected Output:
192.168.1.0
192.168.1.1
...
Actual Output:
Starting Nmap 7.80 ( https://nmap.org ) at 2021-04-12 20:27 EET
Nmap scan report for 192.168.1.0 ...
Upvotes: 1
Views: 181
Reputation: 9377
Similar questions answers this well:
To execute a pipeline, you have to invoke a shell, and then run your commands inside that shell.
Process p = new ProcessBuilder().command("bash", "-c", command).start();
bash
invokes a shell to execute your command and-c
means commands are read from string. So, you don't have to send the command as an array inProcessBuilder
.
String cmd(String command) {
ProcessBuilder builder = new ProcessBuilder();
builder.redirectErrorStream(true); // add stdErr to output
Process process = builder.command("bash", "-c", command).start();
StringBuilder processOutput = new StringBuilder(); // add lines easier
// try-with to auto-close resources
try (BufferedReader processOutputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));) {
String readLine;
while ((readLine = processOutputReader.readLine()) != null) {
processOutput.append(readLine + System.lineSeparator()); // use system's line-break
}
process.waitFor();
}
return processOutput.toString().trim();
}
Then call as expected:
cmd("nmap -sL -n 192.168.1.0/24 | awk '/Nmap scan report/{print $NF}'");
Note: I enhanced it a bit to
StringBuilder
to concatenate output linesSystem.lineSeparator
for platform-independency (Win/Mac/Linux/Unix)Inspired by: read the output from java exec
Upvotes: 2
Reputation: 2365
The pipe is interpreted by the shell. It executes one command then passes the output of one command into the next one. You could emulate this in Java starting both commands and then pumping the OutputStream
of the first program to the InputStream
of the second.
Alternatively if you don't want to do this you can still call something like "sh -c 'command1 | command2"
Upvotes: 1