runtime.getRuntim().exec(somecmd) problem with linux

W

wex

I have used this kind of functionality many times:
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(somecmd);

However I have run into a problem where it will not work when the
command contains a path with spaces in it on a linux platform. For
instance a string that executes any random exec.
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("/path with space/somecmd.bat");

If you executed this command exactly you would get-
java.io.IOException "/path: not found.
Now in windows you would get a similar problem. But the solution is to
pass the command surrounded with quotes embedded into the cmd string
like so:
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("\"/path with space/somecmd.bat\"");

Above works on windows, but on linux you get the same error as before.
I have also tried putting the command in a string array like so:
String[] cmds ={"\"/path with space/somecmd.bat\""};
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmds);
This results in the same error with or without the quotes. I am using
this in a java app that runs on both windows and linux so I am trying
to find a solution that works on both platforms. The quote solution
works with the windows paths but not the linux. If you do however run
the same linux command in a shell using the quotes it works fine so I
can't explain the problem. Does anyone have a solution?
thanks, ryan
 
G

Gordon Beaton

I have used this kind of functionality many times:
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(somecmd);

However I have run into a problem where it will not work when the
command contains a path with spaces in it on a linux platform. For
instance a string that executes any random exec.
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("/path with space/somecmd.bat");

When you use Runtime.exec(String), the string is passed to a
StringTokenizer that breaks the string at whitespace only (i.e.
without regard to any extra quotes) and puts the resulting tokens into
an array. It then calls Runtime.exec(String[]) with the command array.

Obviously this will not work when you have whitespace in the command
or any of the arguments.
I have also tried putting the command in a string array like so:
String[] cmds ={"\"/path with space/somecmd.bat\""};
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmds);
This results in the same error with or without the quotes.

In my experience, this works as expected if you lose the extra quotes.
Just make sure you put the command name and the arguments into a
single element of the array *each*. Exactly what error do you get?

/gordon
 
W

wex

Gordon Beaton said:
I have used this kind of functionality many times:
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(somecmd);

However I have run into a problem where it will not work when the
command contains a path with spaces in it on a linux platform. For
instance a string that executes any random exec.
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("/path with space/somecmd.bat");

When you use Runtime.exec(String), the string is passed to a
StringTokenizer that breaks the string at whitespace only (i.e.
without regard to any extra quotes) and puts the resulting tokens into
an array. It then calls Runtime.exec(String[]) with the command array.

Obviously this will not work when you have whitespace in the command
or any of the arguments.
I have also tried putting the command in a string array like so:
String[] cmds ={"\"/path with space/somecmd.bat\""};
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmds);
This results in the same error with or without the quotes.

In my experience, this works as expected if you lose the extra quotes.
Just make sure you put the command name and the arguments into a
single element of the array *each*. Exactly what error do you get?

/gordon

Thanks, but that doesn't seem to work, I get a java.io.Exception in
the case where it is a single element just a path and command and if
the command is not in a spaced path but one of the arguments has one
it just doesn't work.

I am aware of the string tokenizer effect and thought the solution
would be to pass the whole command string as one element in a String
array because then it would not be manipulated further but that
doesn't seem to work. One of the obstacles I am facing is this path
is dependant on the install location of the app, which is up to the
user installing it. Additionally, the app is suppose to work
seamlessly on windows, linux and mac so even though there may be some
platform specific solutions I am trying to avoid them.

I guess the big question is what happens to the command string after
the string tokenizer parses it? Because just running the simple
command:
String[] cmd = {"/path with space/somecommand"};
runtime.getRuntim().exec(cmd);
Gives me the io exception, it is as if the command is tokenized again
somewhere in the native code.
Help???
 
G

Gordon Beaton

Thanks, but that doesn't seem to work, I get a java.io.Exception

What is the full text of the exception message?
I guess the big question is what happens to the command string after
the string tokenizer parses it?

AFAIK, nothing.
Because just running the simple
command:
String[] cmd = {"/path with space/somecommand"};
runtime.getRuntim().exec(cmd);
Gives me the io exception, it is as if the command is tokenized again
somewhere in the native code.

Try running a short program that does (just) the above, using strace:

strace -f -o strace.log java Testprog

Then look for the command string in the logfile.

/gordon
 
S

Steve Horsley

wex said:
I have used this kind of functionality many times:
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(somecmd);

However I have run into a problem where it will not work when the
command contains a path with spaces in it on a linux platform. For
instance a string that executes any random exec.
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("/path with space/somecmd.bat");


A wild guess that I haven't actually tried - try:
Process process = rt.exec("/path\\ with\\ space/somecmd.bat");

Steve
 
S

steve

Thanks, but that doesn't seem to work, I get a java.io.Exception

What is the full text of the exception message?
I guess the big question is what happens to the command string after
the string tokenizer parses it?

AFAIK, nothing.
Because just running the simple
command:
String[] cmd = {"/path with space/somecommand"};
runtime.getRuntim().exec(cmd);
Gives me the io exception, it is as if the command is tokenized again
somewhere in the native code.

Try running a short program that does (just) the above, using strace:

strace -f -o strace.log java Testprog

Then look for the command string in the logfile.

/gordon

you could try
"/path?with?space/somecommand"

steve
 
W

wex

Steve Horsley said:
A wild guess that I haven't actually tried - try:
Process process = rt.exec("/path\\ with\\ space/somecmd.bat");

Steve

The backslash escaping does not work. Running this command:
cmd = "/home/ryan/documents/work/mbs/MBS\\ PRE/test.cmd";
Process process = rt.exec(cmd);

Results in this:

Nov 7, 2004 7:28:45 PM:processMgr.startAllProcesses, Exception,
java.io.IOException: /home/ryan/documents/work/mbs/MBS\: not found
java.io.IOException: java.io.IOException:
/home/ryan/documents/work/mbs/MBS\: not found
at java.lang.UNIXProcess.<init>(UNIXProcess.java:143)
at java.lang.Runtime.execInternal(Native Method)
at java.lang.Runtime.exec(Runtime.java:566)
at java.lang.Runtime.exec(Runtime.java:428)
at java.lang.Runtime.exec(Runtime.java:364)
at java.lang.Runtime.exec(Runtime.java:326)

There must be a solution???
thanks
-ryan
 
I

Ian A. Mason

You need to avoid Java parsing the String. You need to parse it yourself
and use the

public Process exec(String[] cmdarray)

method of Runtime. I have used this many a time with commands
whose path contains spaces.
 
G

Gordon Beaton

I tried this and could not get it to work. See below for example if
what I tried. What am I doing wrong?

If you still can't get it to work, post *real* code and the *real*
command line, not just snippets with a placeholder command.

/gordon
 
W

wex

You need to avoid Java parsing the String. You need to parse it yourself
and use the

public Process exec(String[] cmdarray)

method of Runtime. I have used this many a time with commands
whose path contains spaces.



I tried this and could not get it to work. See below for example if
what I tried. What am I doing wrong?
Because just running the simple
command:
String[] cmd = {"/path with space/somecommand"};
runtime.getRuntim().exec(cmd);
Gives me the io exception, it is as if the command is tokenized again
somewhere in the native code.
 
A

Andrew Thompson

See below for example if what I tried.

That is BS..
...What am I doing wrong?

1st, you are typing snippets of code that are 'something like'
what your code actually is, but THEY ARE NOT YOUR CODE..

Let's look at your 'example'
.....
String[] cmd = {"/path with space/somecommand"};
runtime.getRuntim().exec(cmd);

This would not compile, since there is no method 'getRuntim()'.

I suggest you stop wasting the time of the people trying to
help you, and posting an *exact* *copy/paste* *example* of what
you are doing, from start to finish. Read this carefully..
<http://www.physci.org/codes/sscce.jsp>

You should be able to make a complete, compilable
example in under 25 lines.
 
A

A. Bolmarcich

I tried this and could not get it to work. See below for example if
what I tried. What am I doing wrong?
Because just running the simple
command:
String[] cmd = {"/path with space/somecommand"};
runtime.getRuntim().exec(cmd);
Gives me the io exception, it is as if the command is tokenized again
somewhere in the native code.

As others have commented, it is difficult to tell what you are doing
wrong without seeing a complete program. Here is a small complete
java program that works for me.


public class Y {
public static void main(String args[]) throws Exception {
Process p = Runtime.getRuntime().exec(new String[]
{"/path with space/somecommand"}
);
p.waitFor();
System.out.println("exit value = " + p.exitValue());
}
}


When run with a /path with space/somecommand file that contains


#!/bin/sh
exit 5


I get the line of output


exit value = 5


Make sure that
- the permissions allow the user running the Java program to read and
execute the file named "/path with space/somecommand"

- the first line of the file named "/path with space/somecommand"
indicates what shell is to interpret the file
 
W

wex

I apologize for not giving more accurate code but I thought it was
easier with the simplistic example which I did test. But anyways the
"real code". My program reads in a properties file that contains
commands. These commands vary based on the type of install
client/server, standalone etc. The command I am having a problem
with, starts a hsql database. When the software starts up a function
that starts all these different processes is run.
The code i use to start it is:
public void startProcess(String cmd)
{
try
{
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmd);
}
catch (Exception e)
{// handle any error
app.handleException(e,"ProcessMgr.startProcess",App.ERR_LOG_DISK|App.ERR_STACK);
}

}

The properties are loaded:
props = new java.util.Properties(defaults);
//load the properties from disk
try
{
props.load(new java.io.FileInputStream(appPath +
appPropertyFile));
if ( ((String)props.get("mode")).length() == 0)
{
// set from the defaults and store properties
props = (java.util.Properties)defaults.clone();
props.store(new java.io.FileOutputStream(appPath +
appPropertyFile),"Radiation Oncology Application Parameters");
}
setAppProperties();//this replaces the <appPath> and <fileSep>
variables properly
}
catch ( java.io.IOException ex)
{
// handle problem with loading application properties
handleException(ex,"Creating application
properties","App.loadAppProperties",


The properties file looks like this:
db_start=java -Xms64m -Xmx128m -cp <appPath>lib<fileSep>hsqldb.jar
org.hsqldb.Server -port 9001 -database <appPath>data<fileSep>med
-silent false -trace false

<appPath> is replaced with the path to the application and the
<fileSep> is replaced with the platform specific file separator. Now
I have bypassed all this in my testing and tried just executing the
command:
String cmd ="java -Xms64m -Xmx128m -cp /home/ryan/documents/program
files/hsqldb.jar org.hsqldb.Server -port 9001 -database
/home/ryan/documents/program files/data/med -silent false -trace
false";
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmd);

And I have of course tried every variation of quotes and backslashes
surrounding the path(notice the space between "program files"):
cmd ="java -Xms64m -Xmx128m -cp \"/home/ryan/documents/program
files/hsqldb.jar\" org.hsqldb.Server -port 9001 -database
\"/home/ryan/documents/program files/data/med\" -silent false -trace
false";

cmd ="java -Xms64m -Xmx128m -cp /home/ryan/documents/program\\
files/hsqldb.jar org.hsqldb.Server -port 9001 -database
/home/ryan/documents/program\\ files/data/med\" -silent false -trace
false";
..
..
etc

I have tried encapsulating the whole command in a string array and
passing that off to rt.exec with various quotes, backslashes, etc.
String[] cmds = {cmd};
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmds);

And of course all of this works fine when there is no space. It also
works completely fine in windows by just putting quotes around the
paths. So I hope this contains some better info for you. Really
appreciate everyone trying to help.
-ryan
 
A

A. Bolmarcich

I apologize for not giving more accurate code but I thought it was
easier with the simplistic example which I did test. But anyways the
"real code".
[snip]
I have bypassed all this in my testing and tried just executing the
command:
String cmd ="java -Xms64m -Xmx128m -cp /home/ryan/documents/program
files/hsqldb.jar org.hsqldb.Server -port 9001 -database
/home/ryan/documents/program files/data/med -silent false -trace
false";
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmd);

As Gordon Beaton and Ian A. Mason wrote in previously replies, this
does not work because exec(String command) breaks the command into
command line arguments at whitespace characters.
And I have of course tried every variation of quotes and backslashes
surrounding the path(notice the space between "program files"):
cmd ="java -Xms64m -Xmx128m -cp \"/home/ryan/documents/program
files/hsqldb.jar\" org.hsqldb.Server -port 9001 -database
\"/home/ryan/documents/program files/data/med\" -silent false -trace
false";

The command is broken up at whitespace characters. The quotes and
backslashes do not make a difference.

[snip]
I have tried encapsulating the whole command in a string array and
passing that off to rt.exec with various quotes, backslashes, etc.
String[] cmds = {cmd};
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmds);

This trys to run a command whose name is the value of cmd. I doubt if
there is a command name starts with

java -Xms64m -Xmx128m -cp /home/ryan/documents/program files/hsqldb.jar

As others have pointed out, you need to use a String[] that has the
command already tokenized into command line arguments. That is, you
need something like

String [] cmds = {"java", "-Xms64m", "-Xmx128m",
"-cp", "/home/ryan/documents/program files/hsqldb.jar",
"org.hsqldb.Server",
"-port", "9001",
"-database", "/home/ryan/documents/program files/data/med",
"-silent", "false",
"-trace", "false"
};
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmds);
And of course all of this works fine when there is no space. It also
works completely fine in windows by just putting quotes around the
paths. So I hope this contains some better info for you. Really
appreciate everyone trying to help.

It works in Microsoft Windows because Microsoft Windows is doing an
extra layer of interpretation of what is exec'ed that Linux does not do.
To Linux putting quotation marks around a value means that the value
contains quotation marks.

You can have Linux do the extra layer of interpretation by running the
command under a shell; the shell will interpret the quotation marks.
However, that is a complication that you don't need. At least you don't
need it yet.

It would have helped if you originally gave the exact value being
used as an argument to the exec method. What you originally wrote was

However I have run into a problem where it will not work when the
command contains a path with spaces in it on a linux platform. For
instance a string that executes any random exec.
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("/path with space/somecmd.bat");

The solution to this problem, which was to use

String[] {"/path with space/somecmd.bat"}

as the argument to exec did not solve your problem because your
problem was that what is being exec'ed is not just the name of a
command, but the name of a command and command arguments.
 
W

wex

A. Bolmarcich said:
I apologize for not giving more accurate code but I thought it was
easier with the simplistic example which I did test. But anyways the
"real code".
[snip]
I have bypassed all this in my testing and tried just executing the
command:
String cmd ="java -Xms64m -Xmx128m -cp /home/ryan/documents/program
files/hsqldb.jar org.hsqldb.Server -port 9001 -database
/home/ryan/documents/program files/data/med -silent false -trace
false";
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmd);

As Gordon Beaton and Ian A. Mason wrote in previously replies, this
does not work because exec(String command) breaks the command into
command line arguments at whitespace characters.
And I have of course tried every variation of quotes and backslashes
surrounding the path(notice the space between "program files"):
cmd ="java -Xms64m -Xmx128m -cp \"/home/ryan/documents/program
files/hsqldb.jar\" org.hsqldb.Server -port 9001 -database
\"/home/ryan/documents/program files/data/med\" -silent false -trace
false";

The command is broken up at whitespace characters. The quotes and
backslashes do not make a difference.

[snip]
I have tried encapsulating the whole command in a string array and
passing that off to rt.exec with various quotes, backslashes, etc.
String[] cmds = {cmd};
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmds);

This trys to run a command whose name is the value of cmd. I doubt if
there is a command name starts with

java -Xms64m -Xmx128m -cp /home/ryan/documents/program files/hsqldb.jar

As others have pointed out, you need to use a String[] that has the
command already tokenized into command line arguments. That is, you
need something like

String [] cmds = {"java", "-Xms64m", "-Xmx128m",
"-cp", "/home/ryan/documents/program files/hsqldb.jar",
"org.hsqldb.Server",
"-port", "9001",
"-database", "/home/ryan/documents/program files/data/med",
"-silent", "false",
"-trace", "false"
};
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmds);
And of course all of this works fine when there is no space. It also
works completely fine in windows by just putting quotes around the
paths. So I hope this contains some better info for you. Really
appreciate everyone trying to help.

It works in Microsoft Windows because Microsoft Windows is doing an
extra layer of interpretation of what is exec'ed that Linux does not do.
To Linux putting quotation marks around a value means that the value
contains quotation marks.

You can have Linux do the extra layer of interpretation by running the
command under a shell; the shell will interpret the quotation marks.
However, that is a complication that you don't need. At least you don't
need it yet.

It would have helped if you originally gave the exact value being
used as an argument to the exec method. What you originally wrote was

However I have run into a problem where it will not work when the
command contains a path with spaces in it on a linux platform. For
instance a string that executes any random exec.
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("/path with space/somecmd.bat");

The solution to this problem, which was to use

String[] {"/path with space/somecmd.bat"}

as the argument to exec did not solve your problem because your
problem was that what is being exec'ed is not just the name of a
command, but the name of a command and command arguments.
Thanks a bunch, it works - that totally clears everything up. It
seems to work with both windows and linux...
 
A

Andrew Thompson

** wex - Via email. **
I recently posted a thread titled "runtime.getRuntim().exec(somecmd)
problem with linux" in the java programmer forum. Andrew - I didn't
want to post this in the java forum cause it has no place there.

Netiquette and asking smart questions has everything to do
with the forum, I'll discuss it here.
But you need to be told -

Join the queu.
..don't be a dick. If you don't want to help people ..

What makes you say that? Because I criticised *you*?
..openly then please don't help, but don't go downtalking people
cause no matter how impressed you are with yourself, and yes it
is pretty obvious, you are you aren't the king of java or the king
of the forums. Cmon man don't be an ass just cause you have some knowledge.

Don't be an ass just because you get criticised for asking a
clueless, time-wasting question.

I have no intention of allowing this community to become infested
with waves of noobs who ask vague questions, tell us code that is
'something like' the actual code they are using, and cannot follow
simple instructions.

My way of doing things works both for me and the many, many people who
*do* appreciate the help. I have no intention of changing my posting
technique. If you are having a problem with that, that is something
you need to take care of at your end.
 
Joined
Oct 18, 2010
Messages
1
Reaction score
0
A. Bolmarcich said:
On 2004-11-09, wex <[email protected]> wrote:
> I apologize for not giving more accurate code but I thought it was
> easier with the simplistic example which I did test. But anyways the
> "real code".


[snip]
> I have bypassed all this in my testing and tried just executing the
> command:
> String cmd ="java -Xms64m -Xmx128m -cp /home/ryan/documents/program
> files/hsqldb.jar org.hsqldb.Server -port 9001 -database
> /home/ryan/documents/program files/data/med -silent false -trace
> false";
> Runtime rt = Runtime.getRuntime();
> Process process = rt.exec(cmd);


As Gordon Beaton and Ian A. Mason wrote in previously replies, this
does not work because exec(String command) breaks the command into
command line arguments at whitespace characters.

> And I have of course tried every variation of quotes and backslashes
> surrounding the path(notice the space between "program files"):
> cmd ="java -Xms64m -Xmx128m -cp \"/home/ryan/documents/program
> files/hsqldb.jar\" org.hsqldb.Server -port 9001 -database
> \"/home/ryan/documents/program files/data/med\" -silent false -trace
> false";


The command is broken up at whitespace characters. The quotes and
backslashes do not make a difference.

[snip]

> I have tried encapsulating the whole command in a string array and
> passing that off to rt.exec with various quotes, backslashes, etc.
> String[] cmds = {cmd};
> Runtime rt = Runtime.getRuntime();
> Process process = rt.exec(cmds);


This trys to run a command whose name is the value of cmd. I doubt if
there is a command name starts with

java -Xms64m -Xmx128m -cp /home/ryan/documents/program files/hsqldb.jar

As others have pointed out, you need to use a String[] that has the
command already tokenized into command line arguments. That is, you
need something like

String [] cmds = {"java", "-Xms64m", "-Xmx128m",
"-cp", "/home/ryan/documents/program files/hsqldb.jar",
"org.hsqldb.Server",
"-port", "9001",
"-database", "/home/ryan/documents/program files/data/med",
"-silent", "false",
"-trace", "false"
};
Runtime rt = Runtime.getRuntime();
Process process = rt.exec(cmds);

> And of course all of this works fine when there is no space. It also
> works completely fine in windows by just putting quotes around the
> paths. So I hope this contains some better info for you. Really
> appreciate everyone trying to help.


It works in Microsoft Windows because Microsoft Windows is doing an
extra layer of interpretation of what is exec'ed that Linux does not do.
To Linux putting quotation marks around a value means that the value
contains quotation marks.

You can have Linux do the extra layer of interpretation by running the
command under a shell; the shell will interpret the quotation marks.
However, that is a complication that you don't need. At least you don't
need it yet.

It would have helped if you originally gave the exact value being
used as an argument to the exec method. What you originally wrote was

However I have run into a problem where it will not work when the
command contains a path with spaces in it on a linux platform. For
instance a string that executes any random exec.
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("/path with space/somecmd.bat");

The solution to this problem, which was to use

String[] {"/path with space/somecmd.bat"}

as the argument to exec did not solve your problem because your
problem was that what is being exec'ed is not just the name of a
command, but the name of a command and command arguments.
=======
Coming in late to this one but you have solved my problem.

In brief. This works.
String [] args = {"gphoto2", "--capture-image-and-download", "--filename="+Path+ProjectName+fileCount+"."+ext, "--force-overwrite"};

Path and ProjectName can have spaces.:beerglas:
 

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,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top