tags:

views:

608

answers:

5
+1  Q: 

Java exec on Unix

I have the Java code below running on Unix (both AIX and Linux), but it doesn't work. If I run this code the file q1.01 is not compressed, and I don't get any exceptions thrown (The file q1.01 exists, and I expect to find the file q1.01.Z after the command runs.) At the command prompt if I type "which compress" it reports back with "/usr/bin/compress". If I type the command "/usr/bin/compress q1.01" at the Unix prompt it works fine. Any ideas on what might be wrong?

String cmd = "/usr/bin/compress q1.01";
Runtime.getRuntime().exec(cmd);
A: 

You probably need to use an absolute path to the file. Capture the output though, to see what the problem is - see this page for info on how to do that.

stevedbrown
A: 

This site may be able to provide some clues.

samoz
+2  A: 

[Later edit: the problem was in the initial description; the OP was passing a wildcard and not q.01. So my answer below is wrong, except for the part in bold. I'm leaving it so the comments after it will make sense.]

It's trying to run /usr/bin/compress as the program name without arguments.

There are many forms of the Runtime.exec() method. You're using the .exec(String) version, which just takes the executable. Instead, you need to use the .exec(String[]) array version, which takes the executable in String[0] and the parameters in String[1..].

.exec() wants a String array for passing arguments.

Try

String[] cmd = new String[] { "/usr/bin/compress", "q1.01" };
Runtime.getRuntime().exec(cmd);

Note that .exec does not call the local command shell. That means we have to do, among other things, wildcard expansion and even some argument parsing before calling .exec(). This is why you can't just pass it your full command line.

lavinio
I don't interpret the Runtime#exec(String) method documentation like that: http://java.sun.com/javase/6/docs/api/java/lang/Runtime.html#exec(java.lang.String,%20java.lang.String[],%20java.io.File) indicates that the argument is broken up into tokens using the StringTokenizer class.
JesperE
Verified. Runtime#exec(String) does indeed split its arguments. Try Runtime.getRuntime().exec("nslookup www.stackoverflow.com").
JesperE
Ah! I had tried this form of the exec method, but I had used "*.01" as the argument, and since it doesn't go through the shell it wasn't expanded. Thanks!
Bill Maier
I concede the point. :( No more ideas here.
lavinio
Hey - I was 1/2 right. Do I get 50% credit? :)There is one other way to diagnose problems like this. Create a shell script which just writes its arguments to a file, and run it. Then look to see what was written.
lavinio
It fixed one problem, but the code still doesn't work. At least now I have several other ideas to try.
Bill Maier
A: 

If the process input stream is null, I suspect that Java wasn't even able to spawn the subprocess. What does Process#exitValue() return?

I'd recommend using strace to see what actually happens on the system-call level. The actual exec() arguments and return code would be especially interesting to see.

JesperE
The process input stream is not null, it's the readLine from the stream that returns null. Apparently there is no output when it runs.
Bill Maier
Many Unix programs display no output at all when they succeed.
JesperE
+1  A: 

There were a couple of problems. One was that I had tried using wildcards, and since the shell isn't invoked they weren't being expanded. The other problem was that I had created very small test files like this: "echo 'abc' >q1.01". This file was so small that compress couldn't compress it any further and so left it alone. (Stupidly, I think when I typed in the command at the shell I used a different filename, which did compress.)

Thanks everyone for the answers. It did help!

Bill Maier