Executing command with Runtime.getRuntime.exec() fails

L

Lionel van den Berg

Roedy said:
or even better:


You don't need a command interpreter to spawn an exe file, but you do
need the explicit .exe.

You also need quotes around filenames with embedded spaces.

Alternatively you could use one of the other exec methods that let you
specify individual parms. Then you don't need the quotes.

We arrived at the right conclusion but thanks for the answer anyway.

FWIW just "cmd /c" works elsewhere, hasn't required cmd.exe. I assume
that's because windows automatically looks for a program with the same
name but with .exe, .com or some other extensions that I don't recall.

Please note the "assume" in the above, I'm just taking a guess from what
I've heard here and there.

Thanks

Lionel.
 
I

Ingo Menger

Ingo said:
Ingo Menger wrote:
I did in fact try using exec(String[]) but perhaps I tokenized it
incorrectly. This is what I tried:
String mysqlServiceCommand[] = {"cmd", "/c",
"C:\\Program Files\\MySQL\\MySQL Server 5.0\\bin\\mysqld-nt.exe\"",
"--install", "MySQL1",
"--defaults-file=\"C:\\Program Files\\MySQL\\MySQL Server " +
"5.0\\my-large.ini\""};
What is the "cmd /c" for, except to make the program less portable?
I think one can trust that Runtime.exec will choose the right command
interpreter.
I was having problems getting it to work in other areas without "cmd /c".
This particular part of the application will only be run if the host is
windows.
This give the same error as before!
Do I need to tokenise at spaces?
No.
Consider how you type this command at the command prompt:
"C:\program files\foo.exe" baz
IMPORTANT: Try it out so that you're sure it works!
Then make a java string that contains *exactly* what you typed. This
means you have to quote backslashes and quotation marks:
String command = "\"C:\\program files\\foo.exe\" baz";
Now pass command to Runtime.exec().
I've done exactly this.
No, you didn't.

Sorry, but I'm afraid I did.

Yes, you're right. Please forgive me for giving wrong advise.
I learned meanwhile that Runtime.exec(String) does it's own
interpretation of the command line string.
Thus, there is simply no way to execute a command with spaces in it's
pathname via exec(String). You need Runtime.exec(String[]) instead, as
suggested in other post.
 
L

Lew

Ingo said:
I see that. Yet it is at if it were designed to mislead former C/C++/
perl Programmers, to lure them into the deception that
Runtime.exec(String) was something like system(3).

It is what it is, and performs as documented.

If there is misleading going on, it's not coming from the API or its
documentation.
 
L

Lew

Ingo said:
I am curious how many java programs contain incomplete, bug ridden
implementations of basic shell features like tokenization, quotation,
wildcard matching, etc. in order to enhance the useless
Runtime.exec(String).

Presumably none, since anyone who needs more advanced forms would use the
other overload of the method and not get mixed up in using the exec(String)
form for things it's not designed to handle.

RTFM.
 
R

Roedy Green

FWIW just "cmd /c" works elsewhere, hasn't required cmd.exe. I assume
that's because windows automatically looks for a program with the same
name but with .exe, .com or some other extensions that I don't recall

the command interpreter is the thing that looks for .com .exe. bat if
you don't specify an extension. The raw exec needs the precise name.
If you don't have it you can use cmd.exe and pass the name to that.

Other os's don't use the .exe extension, so the exeless name is the
precise name.

IT may be that windows has put in a forgiveness hook to allow cmd
without the exe. If so, it has not always been there.
 
L

Lionel van den Berg

Roedy said:
IT may be that windows has put in a forgiveness hook to allow cmd
without the exe. If so, it has not always been there.

I suspect that MS has put this in (windows isn't smart enough to do it
on it's own :)).

You raise an important point though. I have only tested with XP, it
could be that earlier versions will not work. I will rectify by adding
..exe just to be sure.
 
I

Ingo Menger

Presumably none, since anyone who needs more advanced forms would use the
other overload of the method

You call a space in a file name "more advanced"? Disagree.
and not get mixed up in using the exec(String)
form for things it's not designed to handle.

The minor problem is that this means: don't use it at all, since it's
just braindamaged. "Minor problem" since one more useless method is
really not an issue.

But perhaps you can tell us what it is "designed to handle". Perhaps:
Execute a command, when there is neither white space in the command
path name nor in any file names that appear as arguments.
You call that a DESIGN?
 
N

Nigel Wade

Ingo said:
That's exactly my point.


More portable, since on my windows system at least, there is an ls.

On your Windows system maybe, but not on the vast majority of Windows systems.
So not much more portable at all...
But, in fact, the portability does not depend so much on the existance
of a certain executable.

Of course it does. That's what Runtime.exec() is doing, running an external, OS
specific, executable. If the executable you are trying to run only exists on
one OS, or if the argument semantics are different, then the call will fail on
other OSs.
Even if ls is not accessible for some reason (which can happen under
UNIX/LINUX also for other reasons than non-existance), the java
environment still could provide the following abstraction: Execute a
command string in such a way that it works as if one had typed the
command at the command line.

Which command line? My Linux has at least half a dozen different shells to
choose from - e.g. sh,ksh,csh,tcsh,bash all of which are subtely different.
Since there is a lowest common denominator between a unix shell and
cmd.exe about quoting, wildcards, etc. one could go a fairly long way.

Not really. Both quoting and globbing are different between cmd.exe and
UNIX/Linux shells. There are also very many other differences.
Look, I am not saying anything against Runtime.exec(String[]). But the
"convenience" method Runtime.exec(String) is almost useless (since it
does tokenization,

Yes, I agree.
but does not provide for escape mechanism and
ignores quotation). It would be much more convenient (and intuitive,
and simple) to let Runtime.exec(cmdstr) be equivalent to
Runtime.exec(new String[] {"cmd.exe", "/c", cmdstr}); // Win
Runtime.exec(new String[] {"sh", "-c", cmdstr}); // Unix
.... // etc.

The appropriate command interpreter for each os could be found through
a system property.

and there would be no guarantee that the chosen command interpreter would
actually interpret the string in the way the programmer hoped. The only way to
be sure, and programming is about certainty, is to explicitly execute the
correct shell.
I am curious how many java programs contain incomplete, bug ridden
implementations of basic shell features like tokenization, quotation,
wildcard matching, etc. in order to enhance the useless
Runtime.exec(String).

That's why when using Runtime.exec() you should invoke the correct executable,
whether that be a shell/command interpreter or the direct executable, so that
you are not guessing how the these "basic shell features" might get
interpreted.
 
P

Patricia Shanahan

Lionel said:
Oh, so I should be using ProcessBuilder. Hmmmm, why is it that everyone
talks about Runtime.exec(). ProcessBuilder in fact looks a little nicer
to use - on first brief look that is.

It will depend partly on the age of the materials you are reading. The
Runtime.exec methods were the original way of doing this. ProcessBuilder
was added in 1.5, so older books and tutorials ignore it.

Patricia
 
R

Roedy Green

Oh, so I should be using ProcessBuilder. Hmmmm, why is it that everyone
talks about Runtime.exec(). ProcessBuilder in fact looks a little nicer
to use - on first brief look that is.

ProcessBuilder is new and may not be available in the Java the
questioner is using. I point people to
http://mindprod.com/jgloss/exec.html

which explains the use of ProcessBuilder when you have JDK 1.5+.

Most of the advice we hand out applies to both Runtime.exec and
ProcessBuilder, e.g. the use of command interpreters, parsing out the
command line, the path, use of *.exe.
 
L

Lionel van den Berg

Roedy said:
ProcessBuilder is new and may not be available in the Java the
questioner is using. I point people to
http://mindprod.com/jgloss/exec.html

which explains the use of ProcessBuilder when you have JDK 1.5+.

I'm using 1.5 so it's all good. I was aware of that ;).

Most of the advice we hand out applies to both Runtime.exec and
ProcessBuilder, e.g. the use of command interpreters, parsing out the
command line, the path, use of *.exe.

Unfortunately the two behave very differently. I spent about 5 minutes
with ProcessBuilder and found that it didn't work using any of my
original commands and after playing around it was proving to be a pain
to get it to work. I therefore decided to stick with what I have as it's
working nicely now ;).
 
A

Arne Vajhøj

Ingo said:
What is the "cmd /c" for, except to make the program less portable?
I think one can trust that Runtime.exec will choose the right command
interpreter.

I does not.

It runs an executable.

If that executable is not a shell, then there are no shell
being activated.

On Windows platform the targeted exe gets run by CreateProcess
call.

Arne
 
A

Arne Vajhøj

Lew said:
Tsk. That's why there's the (String []) overload. The (String)
overload is only meant as a convenience for the simple case.

No.

exec(String) is a convenience method to execute programs
with no arguments.

exec(String[]) is a convenience method to execute programs
with arguments.

The convenience added is environment and default dir.

exec(String) may accept arguments on some platforms. It does
on Windows. Obviously because CreateProcess accept it. But SUN
could remove that in next release.

Arne
 
N

Nigel Wade

Arne said:
Lew said:
Tsk. That's why there's the (String []) overload. The (String)
overload is only meant as a convenience for the simple case.

No.

exec(String) is a convenience method to execute programs
with no arguments.

exec(String[]) is a convenience method to execute programs
with arguments.

The convenience added is environment and default dir.

That is at variance with what the API says. The API places no restriction on
exec(String) executing programs with no arguments. What is says is:

"This is a convenience method. An invocation of the form exec(command, envp,
dir) behaves in exactly the same way as the invocation exec(cmdarray, envp,
dir), where cmdarray is an array of all the tokens in command.

More precisely, the command string is broken into tokens using a StringTokenizer
created by the call new StringTokenizer(command) with no further modification
of the character categories. The tokens produced by the tokenizer are then
placed in the new string array cmdarray, in the same order."

So exec(String) and exec(String[]) are semantically equal, the only difference
being that in exec(String) the string is broken up by the StringTokenizer and
in exec(String[]) the string is broken up by the programmer. You can use
exec(String) if StringTokenizer splits the string you pass correctly.

[Note: exec(String) is equivalent to exec(String,null,null)]
exec(String) may accept arguments on some platforms. It does
on Windows. Obviously because CreateProcess accept it. But SUN
could remove that in next release.

I don't see what you mean by this. I can't see anything in the documentation
which states any platform dependence on how exec(String) interprets the String,
or anything which Sun might remove in any future release.
 
A

Arne Vajhøj

Nigel said:
Arne said:
Lew said:
Tsk. That's why there's the (String []) overload. The (String)
overload is only meant as a convenience for the simple case.
No.

exec(String) is a convenience method to execute programs
with no arguments.

exec(String[]) is a convenience method to execute programs
with arguments.

The convenience added is environment and default dir.

That is at variance with what the API says. The API places no restriction on
exec(String) executing programs with no arguments. What is says is:

"This is a convenience method. An invocation of the form exec(command, envp,
dir) behaves in exactly the same way as the invocation exec(cmdarray, envp,
dir), where cmdarray is an array of all the tokens in command.

More precisely, the command string is broken into tokens using a StringTokenizer
created by the call new StringTokenizer(command) with no further modification
of the character categories. The tokens produced by the tokenizer are then
placed in the new string array cmdarray, in the same order."

Indeed the docs say so.

I would have sworn that I have seen a command with args fail as
single string on Linux but work with string array (and work on
Windows in both cases).

I must be getting old.

Sorry for the confusion.

Arne
 
N

Nigel Wade

Arne said:
I would have sworn that I have seen a command with args fail as
single string on Linux but work with string array (and work on
Windows in both cases).

The way that Runtime.exec(String command) works doesn't exclude that
possibility. The StringTokenizer could split a command string in such a way
that it didn't work on Linux but did on Windows. The resulting String[] which
was passed to Runtime.exec(String[] cmdarry) would be the same on both
platforms, but exactly how the executable (which is the first element of
cmdarry) handles the rest of the arguments might well be different because the
executable would be different.
I must be getting old.

Sorry for the confusion.

It's the second law of thermodynamics, resistance is futile. You will be
confused. I don't know with whom, but you will be confused. What were we
talking about?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,710
Latest member
bernietqt

Latest Threads

Top