Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / December 2007

Tip: Looking for answers? Try searching our database.

Executing command with Runtime.getRuntime.exec() fails

Thread view: 
Lionel - 29 Nov 2007 11:56 GMT
I wrote this test to show what's happening:

public class TestClass {

    public static void main(String args[]) {
        testMySQLService();
    }

    public static void testMySQLService() {
        MySQLInterfaceManager mysqlInterface =
                MySQLInterfaceManager.getInstance();
        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\"";
        System.out.println(mysqlServiceCommand);
        Process isRunningProcess = null;

        try {
            isRunningProcess =
                    Runtime.getRuntime().exec(mysqlServiceCommand);
            readStandardError(isRunningProcess);
            readStandardOut(isRunningProcess);
            isRunningProcess.waitFor();
        } catch(java.io.IOException ioe) {
            ioe.printStackTrace();
            return;
        } catch(InterruptedException ie) {
            //Assume processing has finished.
            ie.printStackTrace();
            return;
        }
    }

    /**
     * Reads the standard ouput stream of the provided Process one
character at
     * a time until the stream is closed or there is no more data.
Stores the
     * result in standardOut.
     */
    private static void readStandardOut(final Process process) {
        Thread inputStreamThread = new Thread() {
            @Override
            public void run() {
                try {
                    InputStreamReader inputStreamReader =
                            new
InputStreamReader(process.getInputStream());
                    int currentChar;
                    while ((currentChar = inputStreamReader.read()) !=
-1) {
                        System.out.print((char) currentChar);
                    }
                    inputStreamReader.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        };
        inputStreamThread.start();
    }

    /**
     * Reads the error stream of the provided Process one character at
     * a time until the stream is closed or there is no more data.
Stores the
     * result in standardError.
     */
    private static void readStandardError(final Process process) {
        Thread errorStreamThread = new Thread() {
            @Override
            public void run() {
                try {
                    InputStreamReader inputStreamReader =
                            new
InputStreamReader(process.getErrorStream());
                    int currentChar;
                    while ((currentChar = inputStreamReader.read()) !=
-1) {
                        System.out.print((char) currentChar);
                    }
                    inputStreamReader.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        };
        errorStreamThread.start();
    }
}

The output of the above is:

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"
'C:\Program' is not recognized as an internal or external command,
operable program or batch file

If I change mysqlServiceCommand to
"cmd /c \"C:\\Program Files\\MySQL\\MySQL Server 5.0\\bin\\mysqld-nt.exe
--install MySQL1";

It works as expected.

Does anyone have any idea what's going on?

Thanks

Lionel.
Patrick McNicol - 29 Nov 2007 12:06 GMT
> I wrote this test to show what's happening:
>
[quoted text clipped - 109 lines]
>
> Lionel.

Have you tried using Runtime.exec(String[])? That's the one to use if
you have CL arguments.
Gordon Beaton - 29 Nov 2007 12:08 GMT
> If I change mysqlServiceCommand to
> "cmd /c \"C:\\Program Files\\MySQL\\MySQL Server 5.0\\bin\\mysqld-nt.exe
[quoted text clipped - 3 lines]
>
> Does anyone have any idea what's going on?

The string you pass to exec(String) gets tokenized before it's passed
to exec(String[]). The tokenizer breaks your command into whitespace
delimited tokens without regard to escaping, quoting or other special
characters.

In your particular example, you pass your arguments to a command shell
which does further processing to the command line (and probably
respects escapes, quotes etc) before the command itself gets executed
by the shell you specified.

Exactly how the two interact is not always clear, as you've
discovered. Try running a program that simply prints its arguments to
get a better understanding of the situation. Try it both with and
without "cmd /c".

If you want a greater degree of control over this, you can avoid the
initial tokenization done by exec(String) by instead calling
exec(String[]) directly. Break the command into tokens yourself
(exactly one per array element) without using extra quotation marks.

And just for fun, IIRC the actual behaviour is slightly different on
windows and unix platforms, and depends highly on the actual choice of
command shell specified.

/gordon

--
Lionel - 29 Nov 2007 12:23 GMT
>> If I change mysqlServiceCommand to
>> "cmd /c \"C:\\Program Files\\MySQL\\MySQL Server 5.0\\bin\\mysqld-nt.exe
[quoted text clipped - 23 lines]
> exec(String[]) directly. Break the command into tokens yourself
> (exactly one per array element) without using extra quotation marks.

More detailed response of what Patrick also said, so I'll answer both here.

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\""};

This give the same error as before!

Do I need to tokenise at spaces?

thanks

Lionel.
Ingo Menger - 29 Nov 2007 12:43 GMT
> I did in fact try using exec(String[]) but perhaps I tokenized it
> incorrectly. This is what I tried:
[quoted text clipped - 4 lines]
>      "--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.
Actually, this might be the whole problem, since Runtime.exec will
pass your command string to the system default command interpreter
(which does tokenization). So it ends up like
 cmd /c "cmd /c \"your program\""
when you want
 cmd /c "your program"  (on Windows)
and
 sh -c "your prog"   (under Linux)

> 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().
Patricia Shanahan - 29 Nov 2007 12:51 GMT
...
> Consider how you type this command at the command prompt:
>
[quoted text clipped - 5 lines]
>  String command = "\"C:\\program files\\foo.exe\" baz";
> Now pass command to Runtime.exec().
...

Until it works, I suggest printing, or viewing in a debugger, the
command exactly as it will be passed to exec. Make sure that works at a
command prompt.

Patricia
Lionel van den Berg - 29 Nov 2007 13:45 GMT
> ...
>> Consider how you type this command at the command prompt:
[quoted text clipped - 11 lines]
> command exactly as it will be passed to exec. Make sure that works at a
> command prompt.

I answered this in another reply, I've done exactly this. I printed the
command and copy pasted, it worked.

thanks

Lionel
Lionel van den Berg - 29 Nov 2007 13:44 GMT
>> I did in fact try using exec(String[]) but perhaps I tokenized it
>> incorrectly. This is what I tried:
[quoted text clipped - 8 lines]
> 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!
>>
[quoted text clipped - 10 lines]
>  String command = "\"C:\\program files\\foo.exe\" baz";
> Now pass command to Runtime.exec().

I've done exactly this. I printed out the string from the program and
pasted the command into the dos prompt and it's done what I expected.

As you would have seen I did quote back slashes and quotation marks.

thanks

Lionel.
Ingo Menger - 29 Nov 2007 14:44 GMT
> >> I did in fact try using exec(String[]) but perhaps I tokenized it
> >> incorrectly. This is what I tried:
[quoted text clipped - 30 lines]
>
> I've done exactly this.

No, you didn't.
You are actually confused about who does tokenization/interpretation
of the command string. It's the command shell. Every "cmd /c" adds
ANOTHER level of interpretation, so that'd require ANOTHER level of
quotation on your site.
Consider "Tell John: \"Tell Mary: \\\"Tell Joe: \\\\\\\"Jack will give
a party tonight. ... "
This is silly.

It is also hard, since we have TWO sorts of quotations to do: For
once, the quotation that is needed by the command shell itself. Then,
the JAVA-string constant quotation. For example, in the latter we must
quote backslashes, but not in the former.

> I printed out the string from the program and
> pasted the command into the dos prompt and it's done what I expected.

Without the extra cmd /c, I guess.
Lionel van den Berg - 30 Nov 2007 08:22 GMT
>>>> I did in fact try using exec(String[]) but perhaps I tokenized it
>>>> incorrectly. This is what I tried:
[quoted text clipped - 24 lines]
>
> No, you didn't.

Sorry, but I'm afraid I did. You weren't watching me so you can't make
that statement.

First thing I did was start up my windows box running under qemu. I
typed out the install service command to make sure it worked and didn't
throw several errors as it has previously. Once I had the command
correct, I right clicked on the dos prompt at the top to select text,
copied the appropriate text, saved it to a file and placed it in a
network shared folder. Went to the development machine and put it into
code delimiting the quotes and back slashes as appropriate.

I ran the program, I printed out the command using
System.out.println(command) and then when it failed I copied that
command back into the dos prompt and ran it - it worked at dos.

I repeated these things several times before posting here.

>> I printed out the string from the program and
>> pasted the command into the dos prompt and it's done what I expected.
>
> Without the extra cmd /c, I guess.

Yes, sorry for not being explicity.

Thanks

Lionel.
Ingo Menger - 30 Nov 2007 09:20 GMT
> >>>> I did in fact try using exec(String[]) but perhaps I tokenized it
> >>>> incorrectly. This is what I tried:
[quoted text clipped - 26 lines]
>
> 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.
Nigel Wade - 29 Nov 2007 15:30 GMT
>> I did in fact try using exec(String[]) but perhaps I tokenized it
>> incorrectly. This is what I tried:
[quoted text clipped - 8 lines]
> I think one can trust that Runtime.exec will choose the right command
> interpreter.

No, it definitely will not. exec() will run exactly what you tell it to run. If
you don't explicitly include cmd.exe then it will not run cmd.exe. It will
execute the first element from the array if you invoke exec(String[]), or the
first whitespace-delimited sub-string if you invoke exec(String).

> Actually, this might be the whole problem, since Runtime.exec will
> pass your command string to the system default command interpreter

No it won't.

> (which does tokenization). So it ends up like
>   cmd /c "cmd /c \"your program\""
> when you want
>   cmd /c "your program"  (on Windows)
> and
>   sh -c "your prog"   (under Linux)

Neither cmd.exe [on Windows] or sh [on Linux] will be exec'd unless you tell
exec() explicitly to do so by including it as the first argument in the string
(or string array) passed to exec.

>> This give the same error as before!
>>
>> Do I need to tokenise at spaces?

The problem is that an array of strings is getting passed to cmd.exc. The first
argument is the executable you really want to run, and cmd.exe will attempt to
run it. All the other arguments are passed to cmd.exe, not to mysqld-nt.exe.

You can pass a single string to cmd.exe and let it work out how to execute the
string, but you only need to do this if cmd.exe is actually required. If
cmd.exe isn't needed then remove it from the list and invoke mysqld-nt.exe
directly by making it the first element of the array, with the arguments being
passed one per element in the array.

The argument to exec should be either:

String[] { "cmd.exe", "/c", "executable arg1 arg2 ..."}
or
String[] { "executable", "arg1", "arg2" ... }

Signature

Nigel Wade, System Administrator, Space Plasma Physics Group,
           University of Leicester, Leicester, LE1 7RH, UK
E-mail :    nmw@ion.le.ac.uk
Phone :     +44 (0)116 2523548, Fax : +44 (0)116 2523555

Ingo Menger - 29 Nov 2007 16:05 GMT
> >> I did in fact try using exec(String[]) but perhaps I tokenized it
> >> incorrectly. This is what I tried:
[quoted text clipped - 10 lines]
>
> No, it definitely will not.

I just read the API docs and find out to my surprise that you're
right.

I didn't also know that Runtime.exec indeed does tokenization which
makes things more, not less, complicated and does not make any sense,
IMHO.

> exec() will run exactly what you tell it to run.

Sure. In this case
  cmd /c C:\Program     Files\... further args ...

> If
> you don't explicitly include cmd.exe then it will not run cmd.exe.

Too bad for the "run anywhere" approach. Especially when directory
names contain spaces.
Lew - 29 Nov 2007 16:22 GMT
Nigel Wade wrote:
>> If you don't explicitly include cmd.exe then it will not run cmd.exe.

> Too bad for the "run anywhere" approach. Especially when directory
> names contain spaces.

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

And you're talking about Runtime.exec(), whose very definition is to break
such portability.  To take an intentionally non-portable call and blame it
because what it exec()s isn't portable hardly seems fair, now does it?

Signature

Lew

Ingo Menger - 30 Nov 2007 07:04 GMT
> Nigel Wade wrote:
> >> If you don't explicitly include cmd.exe then it will not run cmd.exe.
[quoted text clipped - 3 lines]
> Tsk.  That's why there's the (String []) overload.  The (String) overload is
> only meant as a convenience for the simple case.

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).

> And you're talking about Runtime.exec(), whose very definition is to break
> such portability.  To take an intentionally non-portable call and blame it
> because what it exec()s isn't portable hardly seems fair, now does it?

I don't blame it, I just remark that it would be nice to have a method
that runs a command string without adding another level of
interpretation. The tokenization done by Runtime.exec() is just stupid
IMHO. Now that it is brought to my attention I'll desperately try to
avoid it at all cost.
Lew - 30 Nov 2007 11:32 GMT
> 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.

Signature

Lew

Arne Vajhøj - 02 Dec 2007 03:05 GMT
> 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
Nigel Wade - 03 Dec 2007 17:19 GMT
>> Tsk.  That's why there's the (String []) overload.  The (String)
>> overload is only meant as a convenience for the simple case.
[quoted text clipped - 8 lines]
>
> 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.

Signature

Nigel Wade, System Administrator, Space Plasma Physics Group,
           University of Leicester, Leicester, LE1 7RH, UK
E-mail :    nmw@ion.le.ac.uk
Phone :     +44 (0)116 2523548, Fax : +44 (0)116 2523555

Arne Vajhøj - 04 Dec 2007 03:50 GMT
>>> Tsk.  That's why there's the (String []) overload.  The (String)
>>> overload is only meant as a convenience for the simple case.
[quoted text clipped - 19 lines]
> 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
Nigel Wade - 05 Dec 2007 16:46 GMT
> 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?

Signature

Nigel Wade, System Administrator, Space Plasma Physics Group,
           University of Leicester, Leicester, LE1 7RH, UK
E-mail :    nmw@ion.le.ac.uk
Phone :     +44 (0)116 2523548, Fax : +44 (0)116 2523555

Nigel Wade - 29 Nov 2007 17:05 GMT
>> If
>> you don't explicitly include cmd.exe then it will not run cmd.exe.
>
> Too bad for the "run anywhere" approach. Especially when directory
> names contain spaces.

Runtime.exec() is non-portable. If you use it you shouldn't expect your code to
"run anywhere" other than the platform where the executable you are attempting
to run is valid. Even if exec() had a notion of "intelligence" and did run cmd
on Windows and sh on Linux how portable would, for example, Runtime.exec("ls")
be?

Directory and filenames with spaces are only an issue if you use
the .exec(String) variant which splits the string into fields based on
whitespace delimiters. If you have spaces within an argument use
the .exec(String[]) variant. If you need quotes in an argument it gets messy...

Signature

Nigel Wade, System Administrator, Space Plasma Physics Group,
           University of Leicester, Leicester, LE1 7RH, UK
E-mail :    nmw@ion.le.ac.uk
Phone :     +44 (0)116 2523548, Fax : +44 (0)116 2523555

Ingo Menger - 30 Nov 2007 07:47 GMT
> >> If
> >> you don't explicitly include cmd.exe then it will not run cmd.exe.
[quoted text clipped - 3 lines]
>
> Runtime.exec() is non-portable.

That's exactly my point.

> Even if exec() had a notion of "intelligence" and did run cmd
> on Windows and sh on Linux how portable would, for example, Runtime.exec("ls")
> be?

More portable, since on my windows system at least, there is an ls.
But, in fact, the portability does not depend so much on the existance
of a certain executable.
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.
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.

Look, I am not saying anything against Runtime.exec(String[]). But the
"convenience" method Runtime.exec(String) is almost useless (since it
does tokenization, 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.

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).
Lew - 30 Nov 2007 11:35 GMT
> 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.

Signature

Lew

Ingo Menger - 30 Nov 2007 13:24 GMT
> > I am curious how many java programs contain incomplete, bug ridden
> > implementations of basic shell features like tokenization, quotation,
[quoted text clipped - 3 lines]
> 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?
Nigel Wade - 30 Nov 2007 14:16 GMT
>> >> If
>> >> you don't explicitly include cmd.exe then it will not run cmd.exe.
[quoted text clipped - 11 lines]
>
> 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,
[quoted text clipped - 5 lines]
> 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.

Signature

Nigel Wade, System Administrator, Space Plasma Physics Group,
           University of Leicester, Leicester, LE1 7RH, UK
E-mail :    nmw@ion.le.ac.uk
Phone :     +44 (0)116 2523548, Fax : +44 (0)116 2523555

Arne Vajhøj - 02 Dec 2007 02:58 GMT
> 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
Gordon Beaton - 29 Nov 2007 12:43 GMT
> I did in fact try using exec(String[]) but perhaps I tokenized it
> incorrectly. This is what I tried:
[quoted text clipped - 6 lines]
>
> This give the same error as before!

First, you've got an extra, escaped quote after mysqld-nt.exe. Maybe
you meant to put one at the start of the line too?

Second, I don't think you need cmd /c at all here. Why can't you run
mysqld-nt.exe + arguments directly?

Third, if the shell really is necessary for some reason that isn't
obvious here, I would do it like this:

 { "cmd", "/c", "rest of command, using escaped quotes as necessary" }

I don't use windows (or cmd.exe), but that's the way e.g. /bin/sh
would require it on unix. The entire "rest of command" gets passed
unaltered to the shell, which then does any necessary expansion etc
and then executes the command.

> Do I need to tokenise at spaces?

Not unless your arguments are delimited by spaces (which they don't
seem to be here).

/gordon

--
Lionel van den Berg - 29 Nov 2007 13:59 GMT
>> I did in fact try using exec(String[]) but perhaps I tokenized it
>> incorrectly. This is what I tried:
[quoted text clipped - 9 lines]
> First, you've got an extra, escaped quote after mysqld-nt.exe. Maybe
> you meant to put one at the start of the line too?

Yeah, my bad on that one, shouldn't have been any on that one.

> Second, I don't think you need cmd /c at all here. Why can't you run
> mysqld-nt.exe + arguments directly?

I think I got myself confused at some stage because it wasn't working. I
was sure that another command that I was running with MySQL required the
"cmd /c" to work, maybe it was the "net start mysql". Anyway, I ended up
under a false impression. So I tried again without "cmd /c" and it worked.

Sometimes I just get too deeply involved, I think I have proven
something that in fact I have confused myself, and so I don't take that
avenue again.

I've got responses below, but at this point it is now working - I should
have listened earlier to everyone saying don't use "cmd /c" :).

> Third, if the shell really is necessary for some reason that isn't
> obvious here, I would do it like this:
>
>   { "cmd", "/c", "rest of command, using escaped quotes as necessary" }

Same result doing this.

> I don't use windows (or cmd.exe),

You've got my immediate respect :). I wish I could say the same, but
alas, I am forced into some things.

Thanks

Lionel.
Roedy Green - 30 Nov 2007 07:15 GMT
>   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\"";

you mean cmd.exe

See http://mindprod.com/jgloss/exec.html
for details.
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Roedy Green - 30 Nov 2007 07:21 GMT
>>   String mysqlServiceCommand =
>>                 "cmd /c \"C:\\Program Files\\MySQL\\MySQL " +
[quoted text clipped - 6 lines]
>See http://mindprod.com/jgloss/exec.html
>for details.

or even better:

>>   String mysqlServiceCommand =
>>                 "\"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\"";

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.

Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Lionel van den Berg - 30 Nov 2007 08:30 GMT
>>>   String mysqlServiceCommand =
>>>                 "cmd /c \"C:\\Program Files\\MySQL\\MySQL " +
[quoted text clipped - 21 lines]
> 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.
Roedy Green - 30 Nov 2007 11:39 GMT
On Fri, 30 Nov 2007 18:30:15 +1000, Lionel van den Berg
<lionelv_@gmail.com> wrote, quoted or indirectly quoted someone who
said :

>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.
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Lionel van den Berg - 30 Nov 2007 11:54 GMT
> 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.
Lionel van den Berg - 30 Nov 2007 11:58 GMT
>>   String mysqlServiceCommand =
>>                 "cmd /c \"C:\\Program Files\\MySQL\\MySQL " +
[quoted text clipped - 6 lines]
> See http://mindprod.com/jgloss/exec.html
> for details.

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.
Patricia Shanahan - 30 Nov 2007 14:28 GMT
>>>   String mysqlServiceCommand =
>>>                 "cmd /c \"C:\\Program Files\\MySQL\\MySQL " +
[quoted text clipped - 9 lines]
> 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
Roedy Green - 01 Dec 2007 06:50 GMT
On Fri, 30 Nov 2007 21:58:16 +1000, Lionel van den Berg
<lionelv_@gmail.com> wrote, quoted or indirectly quoted someone who
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.

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.
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Lionel van den Berg - 01 Dec 2007 22:21 GMT
> On Fri, 30 Nov 2007 21:58:16 +1000, Lionel van den Berg
> <lionelv_@gmail.com> wrote, quoted or indirectly quoted someone who
[quoted text clipped - 9 lines]
>
> 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 ;).


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.