tags:

views:

140

answers:

3

Hi, I am trying to execute a program from the Java code. Here is my code:

public static void main(String argv[]) {
    try {
      String line;
      Process p = Runtime.getRuntime().exec(new String[]{
          "/bin/bash", "-c", "executable -o filename.txt"});
      BufferedReader input = new BufferedReader(
          new InputStreamReader(p.getInputStream()));
      while ((line = input.readLine()) != null) {
        System.out.println(line);
      }
      input.close();
    } catch (Exception err) {
      err.printStackTrace();
    }
}

My OS is Mac OS X 10.6.

Now, the executable I am trying to run is supposed to spit the output to filename.txt. If I take this command and run it on the terminal, it works fine and the filename.txt gets populated also. But, from my java program the file is not created.

if instead I use executable > filename.txt then the filename.txt is created but is empty. Not sure what's wrong here. The executable I am trying to run is Xtide (if that helps).

I would really appreciate any help I can get.

Thanks,

+2  A: 

You cannot redirect output to file and read the output in java. It's one or the other. What you want is this:

      Process p = Runtime.getRuntime().exec(new String[]{
          "/bin/bash", "-c", "executable -o filename.txt"});
      p.waitFor();
      BufferedReader input = new BufferedReader(
          new InputStreamReader(new FileInputStream("filename.txt")));
      while ((line = input.readLine()) != null) {
        System.out.println(line);
      }

The main changes are:

  • p.waitFor(), since process execution is asynchronous, so you have to wait for it to complete.
  • The data is read from the file rather than from the output of the process (since this will be empty.)
mdma
The main problem with this is that the filename.txt is not being created by my program. If I use the exact same command on the terminal it does get created. Could you think of any reasons why is it happening? I have already set all the read/write permissions for the folder.
Saurabh Lalwani
I'd make the filename in your command and when creating a FileInputStream absolute, so you don't run into any working directory problems.
mdma
@Saurabh As a guess the process is being terminated early because you did not add p.waitFor().
Kathy Van Stone
@mdma: I am doing that.. but still the file would not show up.@Kathy: I added that statement after mdma pointed it out.
Saurabh Lalwani
Are you sure the process is even being executed? You can check the p.exitValue() to see if that makes sense. As you are no longer using redirection, but a regular command parameter, you can change your execution command to "command","-o","filename.txt". We can always put bash back in once we've identified the problem.
mdma
the exit code it returns is 255. I tried to google for it but could not find anything useful.I tried that too.. but to no avail
Saurabh Lalwani
As well as specifying an absolute path for filename.txt, are you also using a absolute path for your executable?
mdma
There's been a lot of suggestions, and a lot of responses of "I tried that". Please post an update to your question with the code as it is now so we don't need to guess about what you're actually doing.
mdma
+1  A: 

The answer from mdma works (and I voted it up), but you might also want to consider the version where you do read the output stream directly from executable:

Process p = Runtime.getRuntime().exec(new String[]{
          "/bin/bash", "-c", "executable"});
p.waitFor();
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())_;
while ((line = input.readLine()) != null) {
    System.out.println(line);
}
Kathy Van Stone
That was my first try. It did not work that way and hence now my trying to spit the output to a file and read it then.
Saurabh Lalwani
A: 

Correct me if I am wrong, but the symptoms are as follows:

  • exec("/usr/bash", "-c", "executable > filename.txt") creates an empty file.
  • exec("/usr/bash", "-c", "executable -o filename.txt") does not create a file.
  • One or both of the above gives an exit code of 255 when you look at it.
  • When you run the command from the command line as executable -o filename.txt or executable > filename.txt it works as expected.

In the light of the above, I think that the most likely cause is that /bin/bash is not finding the executable when you launch it from Java. The fact that the first example does create an empty file means that /bin/bash is doing something. But if you try to run

$ unknown-command > somefile.txt

from a bash shell prompt you will get an error message saying that the command cannot be found and an empty "something.txt" file. (You would not see the error message in your Java app because it is being written to stderr, and you are not capturing it.) The reason that the empty "something.txt" file is created is that it is opened by the shell before it attempts to fork and exec the "executable".

If this is the problem, then the simple solution is to use the absolute pathname for the executable.

Also, if you are not doing any command line redirection or other shell magic, there is no need to run the executable in a new bash instance. Rather, just do this:

Process p = Runtime.getRuntime().exec("executable", "-o", filename.txt");

then wait for the process to complete and check the exit code before trying to read the file contents.

Stephen C
That's a nice paraphrasing of the comments in my answer! :)
mdma
@mdma - I think I'm doing more than that ...
Stephen C