in reply to Re^2: Running perl from java
in thread Running perl from java

The javadoc is right of course and my too quickly typed code is wrong on that point - input vs. output (another item on the list of things I often confuse). However, I promise you, if you've done it right, passing code snippets does work.

You are using exec(String[]), the one with the array? I'm not at all sure why you are having problems. Are you flushing the output stream before you exit? Throwing away and silencing exceptions? Waiting for the process to finish before querying the output stream? As you know sometimes these problems are in the details or in a small type - an extra quote, a space in the wrong place that the eye doesn't see. Guessing why you are having problems with something that should work is hard without seeing the code.

Here is a working example of code, that did indeed execute a Perl snippet via the -e option. This was run on Debian Linux (Etch), Perl 5.8.8.

import java.io.InputStream; import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.IOException; class RunPerl { public static void main(String[] args) throws IOException { String[] aCmdArgs = { "perl", "-e" , "print \"Hello World, Hello Avi\"" }; Runtime oRuntime = Runtime.getRuntime(); Process oProcess = null; try { oProcess = oRuntime.exec(aCmdArgs); oProcess.waitFor(); } catch (Exception e) { System.out.println("error executing " + aCmdArgs[0]); } /* dump output stream */ BufferedReader is = new BufferedReader ( new InputStreamReader(oProcess.getInputStream())); String sLine; while ((sLine = is.readLine()) != null) { System.out.println(sLine); } System.out.flush(); /* print final result of process */ System.err.println("Exit status=" + oProcess.exitValue()); return; } }

Update: added demo platform.

Replies are listed 'Best First'.
Re^4: Running perl from java
by abramia (Novice) on Jan 09, 2011 at 10:23 UTC
    Elisheva, Many thanks for your code. I tried it but I got the same result. If the command array contains two elements, namely "perl" and the name of a perl script, then the code works fine. However, using your example code verbatim, your java code still indicates that no output was produced.

    Thank you for your help.

      I strongly suggest you post the exact code you ran if you want further help. There are a million times I think I'm doing something "verbatim" and I'm not actually doing so. But whatever issue is at play, it is highly unlikely to be some sort of wierd behavior on the part of the Perl interpreter.

      Some older DOS programs used to do odd things like dumping output to the console/tty rather than to STDOUT. However, to the best of my knowledge, Perl processes code snippets passed in via the "-e" parameter, exactly the same way as it does code loaded from scripts. Both send output to STDOUT, not to a physical device like a console. So the problem has to be either with the arguments you are passing to the perl command or with the java code trying to read from STDOUT.

      I suppose, if you have any concerns about whether or not the -e option really sends output to standard out, you could open up a DOS shell and try piping the output of perl -e to the DOS more command or some other DOS command. However, if you can pipe the output on the command line, then the problem isn't with Perl but with the Java code.

      What did you get for an exit code? Did you check the output to STDERR for any messages? Perhaps that could give you a clue about bad inputs. Also, if your code is part of a running program rather than "main" like mine, you should add a catch clause for that IOException and not just have your Java method throw it. Otherwise you'll never know if you got an IOException. If you get an IOException you'll never reach the lines responsible for extracting the Perl command output. Hence no output. (the IOException is thrown by the lines after the first try...catch)

      As for dealing with timing problems catching the output from an exec'd process, if the code above didn't work, I'm at a loss. I suggest you google/search Java forums for other evidence of problems with Java programs reading the standard out stream of exec'd processes on WIndows platforms. All I can say is that I had no difficulties on a Debian Linux platform running Java 1.6.0_07.

      Sorry I can't be more help.

      Update: added comments about the importance of catching the IOException.

        Well, your program doesn't work for me either :) a quick google and a reading of When Runtime.exec() won't reveals its a combination of common pitfalls and limitations -- essentially, by the time waitFor returns, the buffers are probably empty.

        A modification of GoodWindowsExec.java works without a hitch

        import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class CmndExec { public static void main(String[] args) { String[] cmdArr = new String[]{"CQperl", "-e", "print \"Hello Elisheva\""}; System.out.println("Exit status: " + execute(cmdArr)); } public static int execute(String[] cmdArr) { int returnValue = -1; if (cmdArr != null && cmdArr.length > 0) { Process p = null; Runtime rt = Runtime.getRuntime(); try { p = rt.exec(cmdArr); // throws IOException returnValue = p.waitFor(); // throws InterruptedExc +eption } catch (IOException xIo) { throw new RuntimeException("Error executing command.", xIo); } catch (InterruptedException xInterrupted) { throw new RuntimeException("Command execution interrup +ted.", xInterrupted); } InputStreamReader isr = new InputStreamReader(p.getInputSt +ream()); BufferedReader stdout = null; stdout = new BufferedReader(isr); String line = null; try { while ((line = stdout.readLine()) != null) { System.out.println(line); } } catch (IOException xIo) { throw new RuntimeException("Error reading process outp +ut", xIo); } } return returnValue; } }