Java Runtime.exec woes on Linux - java

I am working on a program in Java designed to be used on a Linux environment that creates a new Java process that runs another Java class, but I am having trouble with it. I have finally fixed all my issues up to this. Invoking
Runtime.getRuntime().exec(new String[] { "/bin/bash", "-c", "'java -classpath /home/kevin/workspace/Misc/bin HelloWorld'" })
in my Java program returns
/bin/bash: /usr/lib/jvm/java-6-openjdk/jre/bin/java -classpath /home/kevin/workspace/Misc/bin HelloWorld: No such file or directory
in either stdout/stderr. If I try
Runtime.getRuntime().exec(new String[] { "/bin/bash -c 'java -classpath /home/kevin/workspace/Misc/bin HelloWorld'" })
I get a Java exception
Cannot run program "/bin/bash -c 'java -classpath /home/kevin/workspace/Misc/bin HelloWorld'": java.io.IOException: error=2, No such file or directory
...
Caused by: java.io.IOException: java.io.IOException: error=2, No such file or directory
And finally, using a simple
Runtime.getRuntime().exec("/bin/bash -c 'java -classpath /home/kevin/workspace/Misc/bin HelloWorld'")
gives me a
-classpath: -c: line 0: unexpected EOF while looking for matching `''
-classpath: -c: line 1: syntax error: unexpected end of file
from stdout/stderr.
Meanwhile, creating a new one line .sh file (and assigning proper permissions) with only this (no #!/bin/bash at the top of the file)
/bin/bash -c 'java -classpath /home/kevin/workspace/Misc/bin HelloWorld'
gives the correct output with no errors.
I understand that the usage Runtime.exec is quite complicated to perfect, and I already solved some big problems I got from it before, but this problem just plain puzzles me (such as Runtime.exec's use of StringTokenizer screwing up any commands that have spaces in them, which is why I invoked the overload that accepts String arrays). However, I'm still getting problems with it and I don't understand why.

Your first attempt was almost correct.
Runtime.getRuntime().exec(new String[] { "/bin/bash", "-c", "java -classpath /home/kevin/workspace/Misc/bin HelloWorld" })
You don't need the extra quoting because passing individual String arguments effectively quotes it automatically.

Related

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

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

Java compiler linux

I was on windows and my compiler code was
#echo off
"C:\Program Files\Java\jdk1.6.0_29\bin\javac.exe" -classpath deps/log4j-1.2.15.jar;deps/jython.jar;deps/xstream.jar;deps/mina.jar;deps/mysql.jar;deps/poi.jar;deps/slf4j.jar;deps/slf4j-nop.jar -d bin src\server\event\*.java src\server\model\items\*.java src\server\model\minigames\*.java src\server\model\npcs\*.java src\server\model\objects\*.java src\server\model\players\*.java src\server\model\players\skills\*.java src\server\model\players\packets\*.java src\server\model\shops\*.java src\server\net\*.java src\server\task\*.java src\server\util\*.java src\server\world\*.java src\server\util\log\*.java src\server\*.java src\server\world\map\*.java
pause
Now when I moved to linux, it doesn't work.
I've tried to change it to .sh file and edited like this
javac -classpath deps/log4j-1.2.15.jar:deps/jython.jar:deps/xstream.jar:deps/mina.jar:deps/mysql.jar:deps/poi.jar:deps/slf4j.jar:deps/slf4j-nop.jar -d bin src/server/event/*.java src/server/model/items/*.java src/server/model/minigames/*.java src/server/model/npcs/*.java src/server/model/objects/*.java src/server/model/players/*.java src/server/model/players/skills/*.java src/server/model/players/packets/*.java src/server/model/shops/*.java src/server/net/*.java src/server/task/*.java src/server/util/*.java src/server/world/*.java src/server/util/log/*.java src/server/*.java src/server/world/map/*.java
Basically I changed ; to :, \ to /
After running sh compile.sh in shell, I get error.
javac: invalid flag: src/server/world/map/*.java
Usage: javac <options> <source files>
use -help for a list of possible options
: not found 2: compile.sh:
Anyone know what I am doing wrong?
Doing a little research it seems this problem might be caused by incorrect line endings in your .sh file. Have you tried completely retyping it in vi, emacs, vim, or something like that?

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

ArrayIndexOutOfBounds Exception on executing linux sh file

I have a program in java which takes 0'th aargument as file location like
File f = new File(args[0]);
so when i execute it using a windows batch(.bat) file it works correctly .
but when i execute the same using a linux shell file(.sh) in linux i get ArrayIndexOutOfBoundsException.
WINDOWS BATCH FILE :
#echo off
for /f %%i in ("%0") do set scriptpath=%%~dpi
set cp=%scriptpath%/../lib/*.jar;
java -classpath %cp% com.synchronizer.main.MYSynchronizer %scriptpath% "%1" "%2"
LINUX SH FILE:
export JAVA_HOME=/usr/local/java
PATH=/usr/local/java/bin:${PATH}
THE_CLASSPATH=
for i in `ls ../lib/*.jar`
do
THE_CLASSPATH=${THE_CLASSPATH}:${i}
done
java -cp ".:${THE_CLASSPATH}" \
com.synchronizer.main.MYSynchronizer
please help!
It looks like a problem in script (no arguments are passed to the Java program).
You can consider to debug the script like this: debugging scripts
Hope this helps
Your shell script is not passing any parameters:
java -cp ".:${THE_CLASSPATH}" com.synchronizer.main.MYSynchronizer
Try:
java -cp ".:${THE_CLASSPATH}" com.synchronizer.main.MYSynchronizer "$1" "$2"
As stated above, your Linux shell script is not sending any arguments to the Java program that you are trying to start.
And, adding to that, you are not showing us how you run the Linux shell script. If no argument is given on the command line when you start the shell script, no arguments can be passed to your Java application from the shell script.
If you want to see the actual command that is going to be run by your shell script, you can always put "echo" in front of a line and see what all variables are expanded to. This is a simple way to debug shell scripts.

Shell file works when run manually but fails when run in CRON

I have a shell file (compile.sh) that compiles then runs a java program. It works when I run it manually on an AIX server but gives me an error when I run it through CRON.
compile.sh :
/usr/java6/bin/javac -classpath :.:/usr/jdk/commons-net-3.0.1.jar:/usr/jdk/classes12.jar:/usr/jdk/mysql-connector-java-5.1.17-bin.jar:/usr/jdk/jtds-1.2.5.jar:/usr/jdk/mail.jar:/usr/jdk/joda-time-1.6.2.jar:/usr/jdk/commons-codec-1.4.jar:/usr/jdk/commons-logging-1.1.1.jar:/usr/jdk/httpclient-4.1.1.jar:/usr/jdk/httpclient-cache-4.1.1.jar:/usr/jdk/httpcore-4.1.jar:/usr/jdk/httpmime-4.1.1.jar:/usr/jdk/mailapi.jar:/usr/jdk/pop3.jar:/usr/jdk/smtp.jar:/usr/jdk/dsn.jar:/usr/jdk/imap.jar -d . daily_transmission.java
java -classpath :.:/usr/jdk/commons-net-3.0.1.jar:/usr/jdk/classes12.jar:/usr/jdk/mysql-connector-java-5.1.17-bin.jar:/usr/jdk/jtds-1.2.5.jar:/urs/jdk/mail.jar:/usr/jdk/joda-time-1.6.2.jar:/usr/jdk/commons-codec-1.4.jar:/usr/jdk/commons-logging-1.1.1.jar:/usr/jdk/httpclient-4.1.1.jar:/usr/jdk/httpclient-cache-4.1.1.jar:/usr/jdk/httpcore-4.1.jar:/usr/jdk/httpmime-4.1.1.jar:/usr/jdk/mailapi.jar:/usr/jdk/pop3.jar:/usr/jdk/smtp.jar:/usr/jdk/dsn.jar:/usr/jdk/imap.jar daily_transmission
error:
/ttms/its/db/dropez/trans/compile_java.sh
javac: file not found: *.java
Usage: javac <options> <source files>
use -help for a list of possible options
Exception in thread "main" java.lang.NoClassDefFoundError: daily_transmission
Caused by: java.lang.ClassNotFoundException: daily_transmission
at java.net.URLClassLoader.findClass(URLClassLoader.java:423)
at java.lang.ClassLoader.loadClass(ClassLoader.java:653)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:346)
at java.lang.ClassLoader.loadClass(ClassLoader.java:619)
Could not find the main class: daily_transmission. Program will exit.
Just change directory before compiling and running :
cd /absolute/path/to/your/project
/usr/java6/bin/javac -classpath :.:/usr/jdk/commons-net-3.0.1.jar:/usr/jdk/classes12.jar:/usr/jdk/mysql-connector-java-5.1.17-bin.jar:/usr/jdk/jtds-1.2.5.jar:/usr/jdk/mail.jar:/usr/jdk/joda-time-1.6.2.jar:/usr/jdk/commons-codec-1.4.jar:/usr/jdk/commons-logging-1.1.1.jar:/usr/jdk/httpclient-4.1.1.jar:/usr/jdk/httpclient-cache-4.1.1.jar:/usr/jdk/httpcore-4.1.jar:/usr/jdk/httpmime-4.1.1.jar:/usr/jdk/mailapi.jar:/usr/jdk/pop3.jar:/usr/jdk/smtp.jar:/usr/jdk/dsn.jar:/usr/jdk/imap.jar -d . daily_transmission.java
java -classpath :.:/usr/jdk/commons-net-3.0.1.jar:/usr/jdk/classes12.jar:/usr/jdk/mysql-connector-java-5.1.17-bin.jar:/usr/jdk/jtds-1.2.5.jar:/urs/jdk/mail.jar:/usr/jdk/joda-time-1.6.2.jar:/usr/jdk/commons-codec-1.4.jar:/usr/jdk/commons-logging-1.1.1.jar:/usr/jdk/httpclient-4.1.1.jar:/usr/jdk/httpclient-cache-4.1.1.jar:/usr/jdk/httpcore-4.1.jar:/usr/jdk/httpmime-4.1.1.jar:/usr/jdk/mailapi.jar:/usr/jdk/pop3.jar:/usr/jdk/smtp.jar:/usr/jdk/dsn.jar:/usr/jdk/imap.jar daily_transmission
** Update **
In fact, cron executes every job from the user's home directory. Therefore, it is best to change your working directory from your shell script. Or even write your query as if you were sitting in your home directory (or root), by specifying absolute paths to every files and folders.

Categories