1

Am calling a p = Runtime.getRuntime().exec(command) on Java 1.8. The command calls a bash script as follows:

#!/bin/bash
args=("$@")
cat /home/user/Downloads/bigtext.txt | grep ${args[0]}

The above bash script works fine when called with the command line. When called within my Java application using exec() I get no CAT output back. it does not seem to get past p.waitFor(); Where am I going wrong?

If I run a command directly such as "ls -alF" every thing works as expected.

$ java -version java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)


String tmp = "/home/user/search "+input;        
System.out.println(tmp); //  /home/user/search sometextarg
String woa = executeCommand(tmp);


private String executeCommand(String command) {     
        StringBuilder output = new StringBuilder();
                BufferedReader reader = null;
        Process p;
        try {
            p = Runtime.getRuntime().exec(command);
            p.waitFor();

                        reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

            String line = "";

            while ((line = reader.readLine())!= null) {
                output.append(line + "\n");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return output.toString();
    }
2
  • How big is bigtext.txt? What are you greping for? Commented Mar 4, 2015 at 2:17
  • its 136 Mb text file Commented Mar 4, 2015 at 12:07

1 Answer 1

3

Your Java process and your script are deadlocked waiting on each other: you are waiting for the process to exit, the process is waiting for you to read the output.

It happens to work for ls -alF and other commands with small outputs because they all fit in the pipe's buffer (64kib on my system).

Just move the p.waitFor() below the while loop, and you'll have more luck:

private String executeCommand(String command) {     
    StringBuilder output = new StringBuilder();
            BufferedReader reader = null;
    Process p;
    try {
        p = Runtime.getRuntime().exec(command);
        reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

        String line = "";
        while ((line = reader.readLine())!= null) {
            output.append(line + "\n");
        }
        p.waitFor();

    } catch (Exception e) {
        e.printStackTrace();
    }
    return output.toString();
}

If you additionally want this to work correctly with values containing spaces and certain other characters, you have to:

  1. Quote "${args[0]}" in your script.
  2. Rewrite your executeCommand to use Runtime.exec(String[]) instead of Runtime.exec(String).
Sign up to request clarification or add additional context in comments.

6 Comments

is waiting for you to read the output Can you explain that?
@SotiriosDelimanolis Your script can write data much, much faster than your Java program can read it. However, that won't cause a mess because instead of pushing data as fast as possible, totally overwhelming the Java program, the script will 1. write a chunk of data, 2. wait for it to be read. 3. repeat as necessary (that's how pipes work). In your case, the script was stuck on step 2, because you weren't reading from the pipe at all, and instead waited for the program to exit.
The part I'd like you to clarify is the that's how pipes work. The spawned process should not be waiting for Java (or any other process) to read from its standard out.
@SotiriosDelimanolis Pipes have a limited buffer. When the buffer is full, processes can't write until it empties. When the buffer is empty, processes can't read until it fills. In the use case you've outlined, this is most definitely what you want. If you have a radically different use case, e.g. strict latency requirements for industrial machinery controllers, please post a separate question about that.
So you're saying the problem is with cat /home/user/Downloads/bigtext.txt | grep ${args[0]} livelocking, hat grep can't proceed because the java process hasn't read its output?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.