2
try {

        String str;
        Process process = Runtime.getRuntime().exec("bash /home/abhishek/workspace/Pro/run");
        InputStream isout = process.getInputStream();
        InputStreamReader isoutr = new InputStreamReader(isout);
        BufferedReader brout = new BufferedReader(isoutr);
        while ((str = brout.readLine()) != null) {
            System.out.println(str);
        }

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

The Code has issues with getting the InputStream from the Process, because if I run the Shell script from my Terminal it runs completely fine, but if I Run the Script like this,the str is always null,

I am using this code to get the output of the Shell Script directly into Java instead writing the Script Output in the File

Is there any other way to achieve this,or how can I get the issue solved using the current approach

3
  • good question, but pretty hard. It has to do with IO blocking which is always pain. However, there is library called akka (akka.io) which claims to overcome such IO blocking problems. I've started to learn it, and I had to admit it has its limitations as well ... Commented Feb 6, 2013 at 11:20
  • Are you sure that the script is printing to stdout rather than stderr? Commented Feb 6, 2013 at 11:49
  • Is there anything returned from process.getErrorStream()? Commented Feb 7, 2013 at 6:42

6 Answers 6

6

I think something returned through the error stream, so you can try to check something from the Process.getErrorStream().

You should also wait for the created process to prevent your main program completes before it. Use Process.waitFor();

public class TestMain {
   private static final String BASH_CMD = "bash";

   private static final String PROG = "/home/abhishek/workspace/Pro/run";

   private static final String[] CMD_ARRAY = { BASH_CMD , PROG };

   public static void main(String[] args) {
      new Thread(new Runnable() {
         public void run() {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                  System.in));
            String command = null;
            try {
               while ((command = reader.readLine()) != null) {
                  System.out.println("Command Received:" + command);
               }
            } catch (Exception ex) {
               ex.printStackTrace();
               // failed to listening command
            }

         }
      }).start();
      Process process = null;
      try {
         ProcessBuilder processBuilder = new ProcessBuilder(CMD_ARRAY);
         process = processBuilder.start();
         InputStream inputStream = process.getInputStream();
         setUpStreamGobbler(inputStream, System.out);

         InputStream errorStream = process.getErrorStream();
         setUpStreamGobbler(errorStream, System.err);

         System.out.println("never returns");
         process.waitFor();
      } catch (IOException e) {
         throw new RuntimeException(e);
      } catch (InterruptedException e) {
         throw new RuntimeException(e);
      }
   }

   public static void setUpStreamGobbler(final InputStream is, final PrintStream ps) {
      final InputStreamReader streamReader = new InputStreamReader(is);
      new Thread(new Runnable() {
         public void run() {
            BufferedReader br = new BufferedReader(streamReader);
            String line = null;
            try {
               while ((line = br.readLine()) != null) {
                  ps.println("process stream: " + line);
               }
            } catch (IOException e) {
               e.printStackTrace();
            } finally {
               try {
                  br.close();
               } catch (IOException e) {
                  e.printStackTrace();
               }
            }
         }
      }).start();
   }
}
Sign up to request clarification or add additional context in comments.

Comments

0

Edit you /home/abhishek/workspace/Pro/run if it is a shell and add the following line on top.

#!/usr/bin/bash

and give required execute permissions to /home/abhishek/workspace/Pro/run.

Then use the following line

Process process = Runtime.getRuntime().exec("/home/abhishek/workspace/Pro/run");

Now if the run program prints anything you should see it in the output.

3 Comments

in linux, there can be a problem with "./run" and "run" if you are executing a program. Line like:Process process = Runtime.getRuntime().exec("/home/abhishek/workspace/Pro/./run"); would not help?
./ is only used to refer relative path. But since we are giving the absolute path like this /home/abhishek/workspace/Pro/run it is not required.
As i said,i am running a Shell Script,so it cannot be ./run at all,if anything run.sh would have made the problem more apparent.
0

Your code looks fine. So, I believe that problem is either in command line you are using (bash /home/abhishek/workspace/Pro/run) or in your script itself.

I'd suggest you to perform the following steps:

  1. try to run some well-known command instead of your script. For example pwd. Check that your code that is reading from input stream works correctly.
  2. Now try to simplify your script. Create script run1 that just runs the same pwd. Now run this script from java and see that it is working. BTW you do not have to run it as bash yourscript. You can directly run it without bash prefix
  3. If all this works start to move from simple to your real script step-by-step. I believe you will find your mistake. Probably your script cannot start for some environment related problems.

1 Comment

Hey I just figured that my output is dependent on an awk program I am running through the script,it prints the output on terminal but however it does not return it to the process through the runtime, so is there a way to carry the awk output into a variable in shell?? I used it like vmstat | awk -f xx.awk the output is printed by the awk file using a print statement, I will now need to get it into a variable in the shell script, your advice helped,I need one last help with this.
0

Possible problem is by the time you obtain inputStram the sub-process is not ready

Try

Process process = Runtime.getRuntime().exec("bash /home/abhishek/workspace/Pro/run");
InputStream isout = process.getInputStream();    
process.waitFor()

1 Comment

Runtime.getRuntime() returns Runtime, not process. @TechExchange, I'd recommend you to remove your answer before receiving downvotes.
0

Try something like this:

String[] runCommand = new String[3];

runCommand[0] = "sh";
runCommand[1] = "-c";
runCommand[2] = "bash /home/abhishek/workspace/Pro/run";

Process process = runtime.exec(runCommand);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = reader.readLine();
reader.close();

Comments

0

After multiple readings of the source code for the unix implementation of Process at https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/unix/classes/java/lang/ProcessImpl.java it seems that the standard redirects will always swallow to a ProcessBuilder.NullInputStream:

    if (redirects[1] == Redirect.PIPE) {
        std_fds[1] = -1;
    }...

and

    stdout = (fds[1] == -1 || forceNullOutputStream) ?
            ProcessBuilder.NullInputStream.INSTANCE :
            new ProcessPipeInputStream(fds[1]);

(The same code repeats for stdIn, stdOut and stdErr streams)

The only workaround I have found, which feels very clumsy is to use a temp File:

    File stdOutTmp;  // create and destroy however you see fit
    ProcessBuilder pb = ...;
    pb.redirectOutput(ProcessBuilder.Redirect.to(stdOutTmp));
    ...

There are other static factory methods (Redirect.appendTo(File) to append to an existing file rather than overwrite an existing file, and Redirect.from(File) for stdIn)

Comments

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.