interactive java invocation is fine but the same in a script fails - java

My script is not running but the same command interactively seems to work. First I try a * wildcard and it fails with a "could not find or load" probably because I want the wildcard to get a Java interpretation, not the Linux interpretation. So I quote the wildcard and then it works: (Java gets the wildcard and interprets it I believe to mean "all the JAR files"). Next I try the same from a script and it fails.
root#server0:~/serverDeployment/application# java -enableassertions
-classpath export/ohana1/* info.zqxj.trader1.CommandProcessor help
Error: Could not find or load main class export.ohana1.commons-collections-3.2.1.jar
root#server0:~/serverDeployment/application# java -enableassertions
-classpath export/ohana1/"*" info.zqxj.trader1.CommandProcessor help
AssertionsEnabled
echoing arguments at the runtime local date 2016 09 06 local time 17:15:01.4...
help
END of echoed arguments.
CommandProcessor: Will process the >help< argument.
CommandProcessor: END of processing the >help< argument.
root#server0:~/serverDeployment/application# cat runner.sh
#!/bin/bash
CLASSPATH='-classpath export/ohana1/"*"'
echo "$CLASSPATH"
java -enableassertions "$CLASSPATH" info.zqxj.trader1.CommandProcessor help
exit 0
root#server0:~/serverDeployment/application# ./runner.sh
-classpath export/ohana1/"*"
Unrecognized option: -classpath export/ohana1/"*"
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
The option is -classpath but for some reason the entire -classpath export/ohana1/"*" is taken to be an option. Why is this happening?
Edit: Costi Ciudatu points out that I double quoted the string -classpath which is true it got double quoted on the line with the java invocation so I stopped doing that in this example that follows. However, it still fails.
root#server0:~/serverDeployment/application# cat runner.sh
#!/bin/bash
CLASSPATH='-classpath export/ohana1/"*"'
echo $CLASSPATH
java -enableassertions $CLASSPATH info.zqxj.trader1.CommandProcessor help
root#server0:~/serverDeployment/application# ./runner.sh
-classpath export/ohana1/"*"
Error: Could not find or load main class info.zqxj.trader1.CommandProcessor
BTW: The echo command seems to indicate that the double quote does no harm, both times I get the contents of the single quote. So echo "$VAR" seems to do the same as echo $VAR so perhaps there is no harm doing the same in the java invocation.

This happens because you put both the option and the value it in double quotes. Try something like:
#!/bin/bash
CLASSPATH='export/ohana1/*'
java -enableassertions -cp "$CLASSPATH" info.zqxj.trader1.CommandProcessor help

Related

How do I run a Command Line script from PowerShell? [duplicate]

I'm trying to run a java process via Powershell in Windows XP. Here's the command:
java.exe -cp .;./common.jar -Dcontext=atest1 -Dresourcepath=. DW_Install
So, the classpath is . and .\common.jar (I think java takes the wrong slashes, right?) There are two environment variables, one "atest1" the other "." and the class to execute main on is DW_Install (in the default package).
This command works in cmd.exe, but doesn't is PS. What's going on? What is PS doing while parsing this command that CMD doesn't do (or vice versa)?
Aaron
The problem is that PS for some reason parses -Dresourcepath=. differently than cmd. What works is
java -cp '.;.\common.jar' -Dcontext=atest1 "-Dresourcepath=." DW_Install
It doesn't matter which way the slash goes, and it doesn't matter which quotes one uses (' or "). The classpath must be escaped, however, with some kind of quotes. A good test to see what's getting by the PS interpreter is to echo it. The following:
echo java -cp '.;.\common.jar' -Dcontext=atest1 -Dresourcepath=. DW_Install
yields the following output:
java
-cp
.;.\common.jar
-Dcontext=atest1
-Dresourcepath=
.
DW_Install
(Notice the resourcepath and the value of resourcepath are not on the same line.) Whereas the output to
echo java -cp '.;.\common.jar' -Dcontext=atest1 '-Dresourcepath=.' DW_Install
yields the following output:
java
-cp
.;.\common.jar
-Dcontext=etaste1
-Dresourcepath=.
DW_Install
Which is much more to our liking.
Although I wish this upon none of you, I hope that this post helps those of you that must deploy java projects on Windows machines (even though they will not run on any other platform ever).
Running external command-line programs from PowerShell is sometimes a bit problematic because there PowerShell exposes two different parsing modes that get trumped by the different syntaxes of said external programs.
In any case, running a command in Powershell requires using either the . prefix (dot-"sourcing") or the & operator.
You can workaround this by passing each parameter to the external program as separate variables, like so:
PS> $classpath = ".;./common.jar"
PS> $env = "-Dcontext=atest1 -Dresourcepath=."
PS> $class = "DW_Install"
PS> . java.exe -cp $classpath $env $class
Another example based on https://gaming.stackexchange.com/questions/24543/how-do-i-change-player-name-in-minecraft-multiplayer-in-offline-mode-in-linux
function mineCraftAs {
Param (
[parameter(mandatory=$true, HelpMessage="Minecraft character name." ,ValueFromPipeline=$true)]
[string] $name
)
if(!(test-path $env:appdata)) { $(throw "Appdata not found at $env:appdata")}
$private:minecraftPath=Join-Path $env:appdata .minecraft
if(!(test-path $minecraftPath)) { $(throw "Minecraft not found at $minecraftpath")}
$private:minebinPath=join-path $minecraftPath "bin"
if(!(test-path $minebinPath)) { $(throw "Minecraft bin not found at $minebinPath")}
$minebinPath | write-debug
gci $minebinpath | write-debug
#java -Xms512m -Xmx1024m -cp "%APPDATA%/.minecraft\bin\*" -Djava.library.path="%APPDATA%\.minecraft\bin\natives" net.minecraft.client.Minecraft '"'%1'"'
echo java -Xms512m -Xmx1024m -cp ('"'+$minebinPath+'\*"') ('-Djava.library.path="'+$minebinPath+'\natives"') net.minecraft.client.Minecraft ($name)
$minecraftJob=& 'C:\Program Files (x86)\Java\jre6\bin\java.exe' -Xms512m -Xmx1024m -cp ('"'+$minebinPath+'\*"') ('-Djava.library.path="'+$minebinPath+'\natives"') net.minecraft.client.Minecraft ($name)
}
minecraftas newbie
The following should work:
java.exe -cp '.;./common.jar' -Dcontext=atest1 -Dresourcepath=. DW_Install
I guess that PowerShell interprets the ; in the classpath as command delimiter, thereby trying to run java -cp . and ./common.jar -D....
start-process -nnw java "-cp .;./common.jar -Dcontext=atest1 -Dresourcepath=. DW_Install"

Executing java program from bash script does not work

I am trying to run a java program (weka) from a bash script. The script takes as arguments an inputfile, an outputfile and the content of file containing the command to run the java program (environment variable $CMD). The script does not work as I wish and informs me that I use an unknown option for java. I tried to echo the command that the program sends to the shell, and the output is exactly the right command. So I assume that the echo output and the command sent to the shell are not the same.
So please tell me: What did I do wrong?
What is the difference between the output I get...
echo "java $(cat $CMD) $in > $out"
...and the command the computer gets?
java "$(cat $CMD)" $in > $out
If more information is needed, please comment!
Edit:
For those familiar with weka (or familiar with java), this is what I want to get, and what is printed to me by echo:
java -cp /usr/share/java/weka.jar weka.filters.supervised.attribute.AttributeSelection -E "weka.attributeSelection.ClassifierSubsetEval -B weka.classifiers.bayes.NaiveBayes -T" -S "weka.attributeSelection.BestFirst -D 1 -N 14" -i /home/aldorado/weka_examples/iris.arff > /home/aldorado/weka_examples/irisselected131113.txt
Add set -x in before the line which causes trouble.
That will make the computer print the command again as it understood it. You will see something like
+ 'java' '-classpath weka.jar name.of.the.main.Class' 'inputFile' > 'outputFile'
Note that quotes which the shell uses to tell you "this was one word / argument for me". It's very useful to notice problems with white space and quoting.
Note that it is very hard to get something like java "$(cat $CMD)" $in > $out working. I suggest to move the java into $CMD. That will allow you to say:
bash "./$CMD" $in > $out
or, if you make the file executable:
"./$CMD" "$in" > $out
Use "$1" in the file $CMD to get a property quoted reference to "$in":
cp="weka.jar"
cp="$cp;other.jar"
cp="$cp;more.jar"
cp="$cp;foo.jar"
java -classpath "$cp" name.of.the.main.Class "$1"

How to launch java executives from bash directly

If I want to launch one java executable java --jar sample.jar from command line, how could I write the bash script? The following doesn' work
#!/usr/bin/java
--jar $HOME/tools/sample.jar
#!/bin/sh
java --jar $HOME/tools/sample.jar
Java is NOT an interpreter and only a script interpreter can be used in the shebang(#!)
To be complete you cant pass parameters to the interpreter that way anyway..
The "correct" but still wrong way would have been
#!/usr/bin/java --jar
$HOME/tools/sample.jar
I am not fully clear, but Wikipedia hints that the second method might just work..
However, it is up to the interpreter to ignore the shebang line; thus, a script consisting of the following two lines simply echos both lines to standard output when run:
#!/bin/cat
Hello world!
#!/bin/bash
exec java -jar /path/to/jar/the-file.jar "$#"
With $# you pass the bash arguments to jar file

setting multiple jar files as classpath in cygwin

I have the program x.java in c:\cygwin\programs\x.java and it uses y.jar and z.jar that are also in the folder c:\cygwin\programs.
In windows:
c:cygwin\programs>javac -classpath c:\cygwin\programs\y.jar;c:\cygwin\programs\z.jar x.java
No errors.
In cygwin
(1)
$javac -classpath c\:/cygwin/programs/y.jar;c\:/cygwin/programs/z.jar x.java
Errors: $'PK\003\004': Command not found.
(2)
$javac -classpath c:\cygwin\programs\y.jar;c:\cygwin\programs\z.jar x.java
Errors: -bash command Command not found.
(3)
$javac -classpath 'c:/cygwin/programs/y.jar;c:/cygwin/programs/z.jar' x.java
No error.
Why is it giving error in case of (1),(2)...
You are messing up with escape character back-slash \. In Unix based environment, it's better to use / as path separator. If you want to use backlashes for some reason, use an additonal backslash i.e. \\ to treat it as literal in the path.
Because of above, first tow statements are not resulting into correct path and hence failure.
Cygwin treats the ; character as starting a new command line, so in (1) it is trying to execute the separate commands
$ javac -classpath c\:/cygwin/programs/y.jar
$ c\:/cygwin/programs/z.jar x.java
The error message is from Cygwin trying to execute the jar file directly as a script.
You can quote the entire argument with '' as in (3), or escape the semicolon:
$ javac -classpath c\:/cygwin/programs/y.jar\;c\:/cygwin/programs/z.jar x.java

How to assign the output of a java method into a bash script variable

I have a bash script that calls a java class method. The method returns a string to the linux console when run independently. how can I assign the value from the java method to a variable in a bash script?
running the script:
java -cp /opt/my_dir/class.method [parameter]
output: my_string
if added in a bash script:
read parameter
java -cp /opt/my_dir/class.method [parameter] | read the_output
echo $the_output
the above doesnt work, I also tried unsuccessfully:
the_output=java -cp /opt/my_dir/class.method [parameter]
the_output=`java -cp /opt/my_dir/class.method [parameter]`
java -cp /opt/my_dir/class.method [parameter] 2>&1
How can i get the output stored into the_output variable?
thanks.
In Bash:
$ the_output="$(java -cp /opt/my_dir/class.method [parameter])"
See: http://www.gnu.org/software/bash/manual/bashref.html#Command-Substitution
EDIT:
Actually, looking at your command-line, I'm surprised that it works. I haven't seen a Java program called like that before. Usuallly you can only run a main() method from a java command. How does yours work?
EDIT:
You say that you are still getting output going to the console when you do this. You may need to capture stderr too:
$ the_output="$(java -cp /opt/my_dir/class.method [parameter] 2>&1 )"
2> means redirect stderr (file descriptor 2). &1 means to the same place as stdout (file descriptor 1) is going.
Use command substitution by wrapping your command in backquotes.
Try bashj (a bash mutant with java support) https://sourceforge.net/projects/bashj/.
for instance:
#!/usr/bin/bashj
X= Math.cos(0.5)
Y= Math.hypot(3.0,4.0)
Z= System.getProperty("java.runtime.version")
You can also put your own methods in a jar loaded by bashj, or include some java source code within the bashj script:
#!/usr/bin/bashj
#!java
public static int factorial(int n)
{if (n<=0) return(0);
if (n==1) return(1);
return(n*factorial(n-1));}
##bash
echo j.factorial(10)
This is much faster than any solution involving the creation of a new JVM process.

Categories