This should be a pretty simple question, I can't believe I wasn't able to find anything from googling.
I'm using powershell and I'm trying to run a java app from command line:
$memory = "-Xms128m -Xmx1028m -XX:MaxPermSize=512m"
$ssl = "-Djavax.rmi.ssl.client.enabledProtocols=`"TLSv1`" -Djavax.rmi.ssl.client.enabledCipherSuites=`"_removed_`" -Djavax.net.ssl.trustStorePassword=`"_removed_`" -Djavax.net.ssl.trustStore=`"_removed_`" -Djavax.net.ssl.keyStorePassword=`"_removed_`" -Djavax.net.ssl.keyStore=`"_removed_`" -Djava.endorsed.dirs=`"$($ddmsLoc)tomcat6\endorsed`""
$classpath = getClasspath "manager" $null
$java_opts = "$($memory) $($ssl) -Djavax.net.debug=all"
$cmd = "$($java) $($java_opts) -cp `"$($classpath)`" dss.vector.solutions.manager.server.ServerStatus -g"
Invoke-Expression $cmd
But for some reason it thinks my JAVA_OPTS parameters are the name of the java class I'm running:
Caused by: java.lang.ClassNotFoundException: .rmi.ssl.client.enabledProtocols=TLSv1
I have tried:
The ssl options with/without quotes around the value
Actually setting the JAVA_OPTS environment variable, until I read somewhere else that the JVM doesn't ever read that variable.
wrapping them in more quotes
I'm kind of at a loss here.
Etan Reisner posted a comment that helped me to solve it:
Why does PowerShell split arguments containing hyphens and periods?
Windows is (for some reason) splitting the parameters in half.
echo -Dmy.param=value
returns:
-Dmy
.param=value
If the parameter is wrapped in quotes, like:
echo "-Dmy.param=value"
Then it works just fine.
Related
I had batch script which executes TestRun class by taking jvm arguments as shown below
java -cp "./lib/*;./statoil.jar" -DURI=localhost:8080 -DOWUser=abc -DOWPassword=abc123 -DpipelineName=EDMStatOil -Ddatabase=edm -DproviderName=141Provider -DdestinationName=110EDM -DproviderWellName=Serno Grad com.statoil.rts.test.TestRun
But while running batch script getting error:
Error: Could not find or load main class Grad
I know it is treating Grad as class file. But how we can avoid this error while passing jvm argument with space?
Java doesn't care if there is a space in the JVM argument's value, but the terminal will split -DproviderWellName=Serno Grad into two command line arguments and pass those to the java executable.
You have to put quotes around the whole argument:
java "-DproviderWellName=Serno Grad"
In you batch file try setting the variable first and then pass that parameter to the actual command like these.
set WellName="Serno Grad"
java -cp "./lib/*;./statoil.jar" -DURI=localhost:8080 -DOWUser=abc -DOWPassword=abc123 -DpipelineName=EDMStatOil -Ddatabase=edm -DproviderName=141Provider -DdestinationName=110EDM -DproviderWellName=%WellName% com.statoil.rts.test.TestRun
OR
set WellName="Serno Grad"
java -cp "./lib/*;./statoil.jar" -DURI=localhost:8080 -DOWUser=abc -DOWPassword=abc123 -DpipelineName=EDMStatOil -Ddatabase=edm -DproviderName=141Provider -DdestinationName=110EDM -DproviderWellName="%WellName%" com.statoil.rts.test.TestRun
On my system either of them works fine.
try with escape characters -DproviderWellName="\"Serno Grad\""
I am trying to use a python script to manipulate the input files for my java program. The way I am doing it is I am generating the file name and passing it to subprocess.call() method to execute. Here is my program:
def execJava(self):
self.thisCmd="pause"
call(self.javaCmd,shell=True)
call(self.pauseCmd,shell=True)
Where,
self.javaCmd = 'java -ea -esa -Xfuture -Xss64m -classpath "C:\FVSDK_9_1_1\lib\x86_64\msc_12.0-sse2_crtdll\*" -Djava.library.path="C:\FVSDK_9_1_1\lib\x86_64\msc_12.0-sse2_crtdll;C:\FVSDK_9_1_1\lib\x86_64\share" com.cognitec.jfrsdk.examples.MatchFIRAgainstGallery C:\FVSDK_9_1_1\etc\frsdk.cfg 0 .\tmp\frsdk-scratch\probe_1.fir .\tmp\test\*'
Yes, it's a long complex java instruction but when I run it in the command prompt it works fine. Only when I pass it as a string it doesn't run and returns:
Exception in thread "main" java.lang.Error
After some exploration into the problem, I have discovered that it is due to \x, \t in the instruction, so it is executing
.\tmp\test\*
as
mp est\*
as it replaces \t with tab space while executing. I have looked up quite a bit and didn't find any solution. Any help is much appreciated.
Use forward slashes "/" instead of back slashes "\" for your paths.
I bumped into this problem today when setting up a local set of communicating programs. Basically one of my applications is sending some data to another, and part of this data is a string containing a command to execute (like you would from the command-line). Let's say, for example:
g++ foo.cc bar.cc -o foobar
is the command sent by my first application. The second application, which receives the command (amongst other things), needs to execute this command after doing some other processing.
Now, at first I thought this would be trivial using a ProcessBuilder:
String exampleCommand = "g++ foo.cc bar.cc -o foobar";
ProcessBuilder builder = new ProcessBuilder(exampleCommand);
builder.start().waitFor();
However this is where the problem occurs.
CreateProcess error=2, The system cannot find the file specified
Okay, no worries I guess I can't just dump the whole thing into the builder. The first part of the command is usually a trivial string so I thought I could probably get away with a split around the first ' ' to separate the program name and arguments.
String exampleCommand = "g++ foo.cc bar.cc -o foobar";
String[] parts = exampleCommand.split(" ", 2);
ProcessBuilder builder = new ProcessBuilder(parts[0], parts[1]);
builder.start().waitFor();
And this brought me a little closer, the g++ file could now be found correctly, however after examining the stderr of g++ I found that the following error had occurred:
g++.exe: error: foo.cc bar.cc -o foobar: No such file or directory
At this point I realised that the ProcessBuilder class must be escaping all arguments passed to it in preparation for the command-line (hence the reason it usually takes arguments as an array of individual arguments rather than just a predefined argument string).
My question is, "Is there any way to pass a raw string of arguments to a ProcessBuilder and say THERE, execute EXACTLY this?"
Because the command comes from another application and is in no way static I can't just break the arguments down into an array beforehand and pass them to the ProcessBuilder constructor properly. The arguments are not so trivial that simply splitting the string around a ' ' will work properly either; arguments might contain spaces escaped with double quotes. For example:
g++ "..\my documents\foo.cpp" bar.cpp -o foobar
Could be a command coming from the application and splitting that string around ' ' and passing it to the ProcessBuilder will result in corrupt arguments.
If there is no proper way to do this can someone please point me to a standalone command line argument parser (in Java) that can turn a command-line string into a valid String[]?
Okay I feel rather foolish now but I achieved my desired result by simply reverting back to the good old Runtime.getRuntime().exec(...). I'll leave the question up in case anyone is as silly as me and find it useful.
String exampleCommand = "g++ foo.cc bar.cc -o foobar";
Runtime sys = Runtime.getRuntime();
sys.exec(exampleCommand);
Easy.
A comment to the Runtime.getRuntime().exec(...) solution:
The Runtime.getRuntime().exec(...) is not good anymore. In java executed on OSX El Capitan, 'Runtime.getRuntime().exec(...)' contains an error that sometimes closes the opened process when the java program exits. It works fine on previous OSX versions. However, ProcessBuilder works on all OSX versions.
(Haven't posted enough to have a enough rep points to make this as a normal comment.)
Example code:
import subprocess
subprocess.call(['java', '-jar', 'temp.jar'])
How to specify the JAVA_OPTS in the above command? I am getting a 'java.lang.OutOfMemoryError: unable to create new native thread' when I use the above command and I think specifying JAVA_OPTS in the command would solve the problem.
I did specify the JAVA_OPTS in .bashrc file and it had no effect.
You can do this, but finding how to do it in the documentation is kind of a wild goose chase.
The subprocess.call() documentation says,
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
The arguments shown above are merely the most common ones, described below in Frequently Used Arguments (hence the slightly odd notation in the abbreviated signature).
Then the Frequently Used Arguments section, says, at the very end after describing a bunch of other arguments:
These options, along with all of the other options, are described in more detail in the Popen constructor documentation.
Well then! The Popen documentation gives the full signature:
class subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
env is the one you want! However, if you just pass env={'JAVA_OPTS': 'foo'}, then that will override all environment variables, including stuff like CLASSPATH, which could break other things. So you probably want to use code like this to add a JAVA_OPTS environment variable for the new process execution, without setting it in the current process:
#!/usr/bin/env python2.7
import os
import subprocess
# Make a copy of the environment
env = dict(os.environ)
env['JAVA_OPTS'] = 'foo'
subprocess.call(['java', '-jar', 'temp.jar'], env=env)
There is no need to use JAVA_OPTS - just pass in some more arguments to call(). For example:
import subprocess
subprocess.call(['java', '-jar', 'temp.jar', '-Xmx1024m', '-Xms256m'])
I have the following shell script. For some reason the java program's standard error and standard output is not printed to the file "log" but instead always appear in the console. Is there a type some where or am I missing something?
JAVACMD="java -XX:+HeapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=19000 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Xss128k -Xmx700m -jar program.jar >log 2>&1 "
echo "Starting server...";
$JAVACMD&
Regrettably, you will have to use eval if you want to keep the redirection operators in the string value.
Like other shell-special characters, redirection operators are only evaluated if they are not quoted. When you expand the JAVACMD parameter it will split on whitespace, but it will not re-evaluate any special characters it includes. Using eval forces this re-evaluation.
The problem with eval is it forces every character be re-evaluated. In your case, none of the other characters will have any untoward affects. If your string value contained some other shell-special character (e.g. ;(){}…) that you did not want the shell to re-evaluate you would have to escape/quote it inside the string value so that eval would not give it a special meaning.
⋮
eval "$JAVACMD &"
To avoid problems with eval, I suggest moving the redirection out of the string value:
JAVACMD="… program.jar"
⋮
$JAVACMD >log 2>&1 &
Done this way the only characters in the string value that you need to watch out for are the whitespace characters (e.g. if you needed some embedded whitespace in one of the options/arguments; if you run into this you might consider using an array variable or "$#" (a singular, array-like variable available in all Bourne-like shells)).
Have you tried:
JAVACMD="java -XX:+HeapDumpOnOutOfMemoryError -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=19000 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Xss128k -Xmx700m -jar program.jar"
echo "Starting server...";
$JAVACMD >log 2>&1 &
The redirections are considered as arguments to the java command as they are contained in the variable.
You can't actually stick redirections in a variable like that and expect bash to accept them. Simple example:
tesla:~ peter$ ECHOCMD='echo > log 2>&1'
tesla:~ peter$ $ECHOCMD
log 2>&1
I.e. your redirection indicators are becoming simple arguments, passed to your java invocation.
One workaround is to say eval $JAVACMD but it won't make your script any cleaner.