Re^5: Running perl from java
by ELISHEVA (Prior) on Jan 09, 2011 at 11:26 UTC
|
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.
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
Well, your program doesn't work for me either - what platform are you on? Please note that the Java program I wrote does not process command line arguments like your script does below. The call to perl is entirely hardcoded and the script should only output is "Hello World, Hello Avi\n".
Looking at that article, I'm wondering where you found concerns that the buffer is liable to be emptied out before Java code has a chance to read it. The problems it discusses don't seem related to that at all. They also don't seem to explain Avi's failed output. They include:
the command causing thread violations by failing to wait for the process to finish before fetching the exit code. Avi's script (and mine) only check the exit code after calling waitfor so this isn't an issue here.
the command hanging due to buffer overflow- The issue being discussed in the article are buffers that are too full, not buffers emptied out. The overfull buffer prevents the process from further writes and it hangs waiting for the buffer to empty out so it can do the next write. This is the exact opposite of a buffer that empties out by the time the process finishes. Even if the process doesn't hang, the symptom of this problem would be truncated output (only the first N characters), not entirely missing output.
Although the risk of buffer overflow merits a change to the script I offered (to poll output while the process is running rather than slurping it after the process completes), it does not explain Avi's lack of output. Also, Avi did not report hanging. In any case it is unlikely that the maximum buffer size for interprocess communication on MsWin is < 32 bytes. ("hello world. Hello avi!\n" is 26 characters (26 bytes UTF8, I believe since all the characters are Latin1)).
seeing no output because the command spits output to stderr, and the programmer is only checking stdout. This program is clearly writing to stdout, so this does not apply either.
seeing no output because the command was a built-in shell command and can't be run without calling "cmd.exe". Neither perl, ratlperl, nor cqperl are built-in shell commands.
The author's solution is also somewhat questionable: passing everything to "cmd.exe". This introduces additional issues of shell interpretation, quoting, etc and generally makes the calling process more complex. It also adds overhead as we now need to launch 2 processes (cmd.exe and cqperl.exe) rather than 1. Avi ought to be able to call his command without diving into the "cmd.exe" and if he can't something is wrong that needs to be understood.
| [reply] [d/l] [select] |
|
|
|
|
| [reply] |
|
|
|
|
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;
}
}
| [reply] [d/l] |
|
|
As long as I change "CQPerl" to "perl", your code works on my machine, happily printing out "Hello Elisheva".
I wonder if the issue is cqperl itself. This document suggests that cqperl (Clear Quest Perl by IBM/Rational Rose) is not designed to work as the standard Perl interpreter. http://www-01.ibm.com/support/docview.wss?uid=swg21265812 states that: cqperl is not a Perl interpreter of its own. It uses the $0 variable to determine which part of ClearQuest to run, but $0 is not set if called from the "shebang" line [ of a script. ]. I wonder if cqperl even knows what where to send the argument to "-e"? Is this a valid option letter for cqperl? The article goes on to say that you need to explicitly call "ratlperl" not "cqperl" in your shebang line. It also seems to assume that you've included "use CQPerlExt" as the first line in the script, though I'm guessing that is only necessary if you want to interact with the Clear Quest API in your script.
What happens if you replace "cqperl" with "ratlperl" in your command args array? Do you get a different result? I wonder if your script is working because it has the right shebang line, but that cqperl -e is failing because cqperl just doesn't know what to do with the "-e" option. What does your documentation say about cqperl and ratlperl command line arguments? Perhaps it is time to look at vendor forums? or make a support call?
| [reply] [d/l] [select] |
|
|
|
|
|
|