How to read the output of an exec process in Java? - java

Writing some Java code for running a text executable file under Linux, I have a problem to print out the output of it. This executable file is actually a nmap -sP and so receives to parameters.
Everytime I call for the compiled class, I only can see the first output line but nothing else.
This is the runFile.java file:
import java.lang.Runtime;
import java.lang.Process;
import java.io.*;
import java.lang.InterruptedException;
public class runFile {
public static void main (String args[]) throws IOException, InterruptedException {
Runtime r = Runtime.getRuntime();
Process p = r.exec("/home/diegoaguilar/Dropbox/Buap/SO/file.exe "+args[0]+args[1]);
InputStream stream = p.getInputStream();
BufferedReader reader = new BufferedReader (new InputStreamReader(stream));
String salida = reader.readLine();
while (salida != null) {
System.out.println(salida);
salida = reader.readLine();
}
//p.waitFor();
}
}
So, this is the content of file.exe:
nmap -sP $segment1-$segment1
No matter what arguments, either valid or not I call runFile with, it's always printed to the console something like the first line:
Starting Nmap 5.21 ( http://nmap.org ) at 2013-08-25 02:09 CDT

How about sending the output to a temp file and then reading that file.
Process p = r.exec("/home/diegoaguilar/Dropbox/Buap/SO/file.exe
"+args[0]+args[1]+" > temp.output");
Now output will go to temp.output file and you should be able to read it easily.

Read the inputstream and errorstream in a separate thread. Also, wait for the threads to join. This will read all messages until command is executed.
LogStreamReader is my custom thread to read streams.
Runtime r = Runtime.getRuntime();
Process p = r.exec(cmd);
LogStreamReader lsr = new LogStreamReader(p.getInputStream(), "INPUT");
Thread thread = new Thread(lsr);
thread.start();
LogStreamReader lsr2 = new LogStreamReader(p.getErrorStream(), "ERROR");
Thread thread2 = new Thread(lsr2);
thread2.start();
thread2.join();
thread.join();

Try putting p.waitFor(); after Process p = r.exec("/home/diegoaguilar/Dropbox/Buap/SO/file.exe "+args[0]+args[1]);

Related

Creating named pipes in Java

I am experimenting with creating named pipes using Java. I am using Linux. However, I am running into a problem where writing to the pipe hangs.
File fifo = fifoCreator.createFifoPipe("fifo");
String[] command = new String[] {"cat", fifo.getAbsolutePath()};
process = Runtime.getRuntime().exec(command);
FileWriter fw = new FileWriter(fifo.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(boxString); //hangs here
bw.close();
process.waitFor();
fifoCreator.removeFifoPipe(fifo.toString());
fifoCreator:
#Override
public File createFifoPipe(String fifoName) throws IOException, InterruptedException {
Path fifoPath = propertiesManager.getTmpFilePath(fifoName);
Process process = null;
String[] command = new String[] {"mkfifo", fifoPath.toString()};
process = Runtime.getRuntime().exec(command);
process.waitFor();
return new File(fifoPath.toString());
}
#Override
public File getFifoPipe(String fifoName) {
Path fifoPath = propertiesManager.getTmpFilePath(fifoName);
return new File(fifoPath.toString());
}
#Override
public void removeFifoPipe(String fifoName) throws IOException {
Files.delete(propertiesManager.getTmpFilePath(fifoName));
}
I am writing a string that consists of 1000 lines. Writing 100 lines work but 1000 lines doesn't.
However, if I run "cat fifo" on an external shell, then the program proceeds and writes everything out without hanging. Its strange how the cat subprocess launched by this program doesn't work.
EDIT: I did a ps on the subprocess and it has the status "S".
External processes have input and output that you need to handle. Otherwise, they may hang, though the exact point at which they hang varies.
The easiest way to solve your issue is to change every occurrence of this:
process = Runtime.getRuntime().exec(command);
to this:
process = new ProcessBuilder(command).inheritIO().start();
Runtime.exec is obsolete. Use ProcessBuilder instead.
UPDATE:
inheritIO() is shorthand for redirecting all of the Process's input and output to those of the parent Java process. You can instead redirect only the input, and read the output yourself:
process = new ProcessBuilder(command).redirectInput(
ProcessBuilder.Redirect.INHERIT).start();
Then you will need to read the process's output from process.getInputStream().

Open new terminal, ssh to remote host and run a program to the remote host.All output to be viewed on new opened terminal

To be more specific, what i really want to do is to open two new terminals. From terminal_1 i want to ssh #host1 and run a program1 to host1. From terminal_2 i want to ssh #host2 and run a program2 to host2. I need the output of program1 to be viewed on terminal_1 and output of program2 to be viewed on terminal_2.
(I have managed to open xterm and ssh #host.I tried to pass a second command "&&java echo_1" but it does nothing at all)
Here is the code:
import java.io.*;
public class multi1 implements Runnable {
public void run() {
try {
String ss = null;
Runtime obj = null;
String[] newcmd = new String[]{"/usr/bin/xterm","-hold","-e","ssh andreas#192.168.0.0&&java echo_1"};
Process p = Runtime.getRuntime().exec(newcmd);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((ss = stdInput.readLine()) != null) {
System.out.println(ss);
}
}catch (IOException e) {
System.out.println("FROM CATCH" + e.toString());
}
}
public static void main(String[] args) throws Exception {
Thread th = new Thread(new multi1());
th.start();
//Thread th2 = new Thread(new multi1());
//th2.start();
}
}
I rather use jsch or other ssh library and do it without terminals and exec.
One concern I have immediately is that you're not handling the stdout/stderr from the spawned process. If you don't do this, it's likely that you'll block the output from the process and the process itself. See this answer for more info.
BufferedReader stdError = ..
..would be flagged a warning by Eclipse as it does not seem to be referenced again. That in turn would indicate that the error stream is not being consumed. Do so.
For more tips on using a Process, see the article linked in the runtime.exec info. page. Also, better to use a ProcessBuilder, which can merge the System.out and System.err, making it easier to consume both with one loop.

runtime.exec() taking infinite time to execute code

I want to execute a command which takes 2 arguments.
1.input file name
2.output file name.
The command is sixV1.1 outputFile.txt
The code is:
String cmd= "sixV1.1 <inputFile.txt >outputFile.txt";
Process p=Runtime.getRuntime().exec(cmd);
int retValue=p.waitFor();
when the i run above code,it is taking infinite time.
Is it possible to give <, > charecters in cmd .Please suggest me....
The right way to do input/output redirection when you start a process in Java is to write/read from the process's streams:
Process p = Runtime.getRuntime().exec("sixV1.1");
InputStream is = p.getInputStream();
// read from is and write to outputFile.txt
OutputStream os = p.getOutputStream();
// read from inputFile.txt and write to os
There's a fantastic blog post by Michael C. Daconta about successful command line calls using Runtime in Java. It's not as easy as you might think!
The following code extract from that blog post describes "MediocreExecJava", a class that successfully runs a program using Runtime.exec() and manages its input and output without hanging. I've used it before and it works. I highly recommend reading the post to understand why!
import java.util.*;
import java.io.*;
public class MediocreExecJavac
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
InputStream stderr = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<ERROR>");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("</ERROR>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}

read output from a class executed as a process

I am using Runtime.getRuntime().exec(test.class) to create a process and launch a test.class file.
test.class:
public class test {
public static void main(String[] args) {
doReturn();
}
public static String doReturn() {
System.out.println("printed output");
return "returned output";
}
}
in the Java application launching this process, I'd like to retrieve the output of this test.class
The code I use looks like:
Process proc = null;
String[] cmd = { "java", "test"};
proc = Runtime.getRuntime().exec(cmd);
InputStream inputStream = proc.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null)
{
System.out.println(line);
}
This snippet of code does not work: nothing is printed and I get an Exitvalue of 1 for my process.
=> How should I modify it (and / or modify test.class) to return "printed output" to my java application?
=> Is it possible to return "returned output" as well?
(I am new to Java so could you please be very detailed in your answers! Thx!)
I don't know what are you want to do but try to remove the .class
String[] cmd = { "java", "test"};
Try the commons exec library. It simplifies a lot of code that otherwise you would have to write. You will need to capture the inputstream from the process on another thread. There are issues in doing it on the same thread.. Some info here:
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
And the commons exec library here:
http://commons.apache.org/exec/

Redirect process output to stdout

I would like to execute foo.bat from within a Groovy program and have the resulting process' output redirected to stdout. Either a Java or Groovy code example would be fine.
foo.bat can take several minutes to run and generates a lot of output, so I would like to see the output as soon as it is generated, rather than having to wait until the process has completed before seeing all the output at once.
It is simple to redirect all your stream to standard output using inheritIO() method. This will print the output to the stdout of the process from which you are running this command.
ProcessBuilder pb = new ProcessBuilder("command", "argument");
pb.directory(new File(<directory from where you want to run the command>));
pb.inheritIO();
Process p = pb.start();
p.waitFor();
There exist other methods too, like as mentioned below. These individual methods will help redirect only required stream.
pb.redirectInput(Redirect.INHERIT)
pb.redirectOutput(Redirect.INHERIT)
pb.redirectError(Redirect.INHERIT)
This uses a class which reads all output the executed program generates and displays it in it's own stdout.
class StreamGobbler extends Thread {
InputStream is;
// reads everything from is until empty.
StreamGobbler(InputStream is) {
this.is = is;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(line);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
//output both stdout and stderr data from proc to stdout of this process
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream());
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream());
errorGobbler.start();
outputGobbler.start();
proc.waitFor();
If you're looking to do this with more Groovy and less java, this will print each line as it happens:
def cmd = "./longRunningProcess"
def process = cmd.execute()
process.in.eachLine { line -> println line }
Alternatively, if you want to see both stdout and stderr
def cmd = "./longRunningProcess"
def process = cmd.execute()
process.waitForProcessOutput( System.out, System.err )
Here's something a little simpler if you're just trying to grab the output of a simple command. You'll need to use threads like jitter does if you want to process in parallel or if your command takes stdin or generates stderr.
Use a buffered copy (like this) if you're getting lots of output.
import java.io.*;
public class test {
static void copy(InputStream in, OutputStream out) throws IOException {
while (true) {
int c = in.read();
if (c == -1) break;
out.write((char)c);
}
}
public static void main(String[] args) throws IOException, InterruptedException {
String cmd = "echo foo";
Process p = Runtime.getRuntime().exec(cmd);
copy(p.getInputStream(), System.out);
p.waitFor();
}
}
The following Groovy code will execute foo.bat and send the output to stdout:
println "foo.bat".execute().text
Asynchronous way to achieve it.
void inputStreamToOutputStream(final InputStream inputStream, final OutputStream out) {
Thread t = new Thread(new Runnable() {
public void run() {
try {
int d;
while ((d = inputStream.read()) != -1) {
out.write(d);
}
} catch (IOException ex) {
//TODO make a callback on exception.
}
}
});
t.setDaemon(true);
t.start();
}
{
Process p = ...;
inputStreamToOutputStream(p.getErrorStream(), System.out);
inputStreamToOutputStream(p.getInputStream(), System.out);
}
VerboseProcess from jcabi-log can help you:
String output = new VerboseProcess(new ProcessBuilder("foo.bat")).stdout();

Categories