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"
Related
I have a script that ideally will be used in two different ways. One, run stand-alone from command line. Two invoke from a service script located in /etc/init.d.
I would like the script (call it run_app.sh) to work as follows:
#/bin/bash
# this is run_app.sh. It should be able to be run stand-alone or called from another script
if [ invoked by a calling script ] then
java -cp . -jar blah.jar
else
nohup java -cp . -jar blah.jar 2>&1 &
, so its the "invoked by a calling script" that I would need help with. Thank you.
If you plan to launch your script either by issuing ./run_app.sh or the service. You can just use $0:
#!/bin/bash
# this is run_app.sh. It should be able to be run stand-alone or called from another script
this_script_name="run_app.sh"
if [ "$0" == "./${this_script_name}" ] then
java -cp . -jar blah.jar
else
nohup java -cp . -jar blah.jar 2>&1 &
Instead of trying to find out how the script was called, I suggest to use a command line argument.
Script app.sh
#/bin/bash
# this is run_app.sh. It should be able to be run stand-alone or called from another script
if [ "$1" = "--service" ] then
java -cp . -jar blah.jar
else
nohup java -cp . -jar blah.jar 2>&1 &
fi
Manually run the script as app.sh, from the calling script run app.sh --service.
If you need to pass additional command line arguments to your script, you might have to implement some better option parsing.
Note: Checking $0 may work under certain conditions, but may not work in some other cases. Trying to find out details about the parent processes is even more difficult and fragile.
Another note: Your java command line arguments -cp . -jar blah.jar depend on the current directory. To make sure this works in all cases, the script should cd into the correct directory before calling java. e.g. cd $(dirname "$0") if the script is located in the same directory as blah.jar.
I'm following a guide that only includes compilation instructions on windows. How would one run this build.bat file on Linux?
The batch file looks like this:
#echo off
#echo Compiling...
javac -classpath ..\..\lib\OneWireAPI.jar;%classpath% -d . .\src\*.java
And when I run the javac command on Linux, it fails:
javac -classpath ../../lib/OneWireAPI.jar;%classpath% -d . ./src/ReadTemp.java
The output is:
javac: no source files
What is the correct way to do this?
On Linux, you have to use : (colon) in place of ; (semicolon) as the path separator in Java options.
Also, if you have a classpath variable, in most common Linux shells it is referenced by $classpath rather than by %classpath%
javac -classpath ../../lib/OneWireAPI.jar:$classpath -d . ./src/ReadTemp.java
You have two items that did not get translated correctly from Windows CMD to Unix:
Path separator ; should be :.
Environment variables should be changed from %classpath% to $CLASSPATH format. Note that pretty much everything is case-sensitive in Linux, including environment variable names, and the Java path is traditionally all-caps.
Try
javac -classpath ../../lib/OneWireAPI.jar:$CLASSPATH -d . ./src/ReadTemp.java
I programmed a Java app. For complex reasons I cannot export it as an executable (due to CVS and environment promoting practices) to Linux. I also cannot add the main class path to the MANIFEST.MF via 'jar -cvmf' command because it is not installed in the Linux environment the app is running in (I have no control over what gets installed). The only other option I found was to create the following shell script:
#!/bin/bash
#check that parameters were passed
if [ $# -lt 2 ]; then
echo ""
echo "Not enough arguments provided. You must have at least 2 arguments with ISO SQL time stamps."
echo " After that you can have unlimited number of parameters for tools."
echo ""
exit 1
fi
echo "Recovering events that occurred between $#"
ROOT_DIR=_spool_generator
JAR_DIR=jar
mkdir $ROOT_DIR
mkdir $ROOT_DIR/$JAR_DIR
FULL_DIR=$ROOT_DIR/$JAR_DIR
cp /home/wma/jar/SpoolGenerator.jar ./$FULL_DIR/
echo $#
START=$1
END=$2
java -cp "./$FULL_DIR/SpoolGenerator.jar" com.btv.main.Driver $# # --> does not work
#java -cp "./$FULL_DIR/SpoolGenerator.jar" com.btv.main.Driver "2001-02-12 18:15:00.0" "2001-02-12 19:15:00.0" --> works
#java -cp "./$FULL_DIR/SpoolGenerator.jar" com.btv.main.Driver "$START" "$END" --> works
echo "Execution is complete..."
exit
The key issue here is that I have an unlimited number of parameters the application uses. This works great when deploying the java app directly as an executable in Windows, works fine if I specify the positional arguments the Shell script takes, but how do I pass these same arguments to the java app from within the Linux script. I have to pass the parameters to the script surrounded in quotes due to the timstamp's special characters, this seems to cause some aberrant parsing when the parameters are passed to the jar. I appreciate any help.
I am starting a java programm under Red Hat Enterprise Linux Server release 5 (Tikanga).
directory structure:
- bin ->sc.jar,start-sc.sh,sc-lib-all.jar
- conf->log4j-sc.properties,sc.properties
command to run the java programm (which is perfectly working):
/usr/java/jdk1.6.0_37/bin/java -Xmx1024M -Dlog4j.configuration=file:../conf/log4j sc.properties -jar sc.jar -config ../conf/sc.properties
if i put it into a shell script the java programm can't find the prop file anymore.
shell script (start-sc.sh) looks like:
#!/bin/sh
/usr/java/jdk1.6.0_37/bin/java -Xmx1024M -Dlog4j.configuration=file:../conf/log4j-sc.properties -jar sc.jar -config ../conf/sc.properties
i am a newbie on shell scripting any ideas what i am missing? thx!
i guess you started your shell script not from the bin directory, which the dir start-sc.sh belongs to.
to explain it clear, let's make an example.
say, your script is here:
/foo/bar/bin/start-sc.sh
if you start it under /foo/bar/bin/, it (the relative path) should work.
but if you start your script from /home/yourHome/someDir/ , the relative path will point to $PWD/../, which is /home/yourHome/
you could either in your script first cd /foo/bar/bin/ before you start the java app. or do something like:
a=`dirname $0`
if [ $a = '.' ];then
a=`pwd`
fi
cd $a
/usr/java/jdkxxxx/java .....
It sound fine to me, does this version work?
#!/bin/sh
/usr/java/jdk1.6.0_37/bin/java -Xmx1024M -Dlog4j.configuration=file:$(pwd)/../conf/log4j-sc.properties -jar sc.jar -config $(pwd)/../conf/sc.properties
Edit #1:
Try put the following before launching your program:
echo `pwd`
The output tells you where you are running your script, so you can check if it's the right path or not.
Edit #2:
Try this script
#!/bin/bash
LOG4JCONF="/absolute/path/to/the/log4j/conf/file"
SCCONF="/absolute/path/to/the/other/conf/file"
/usr/java/jdk1.6.0_37/bin/java -Xmx1024M -Dlog4j.configuration=file:$LOG4JCONF -jar sc.jar -config $SCCONF
I've been experiencing a strange issue the last couple of days while writing a shell script which executes Java (starting the JBoss AS). I have a variable JAVA_OPTS that I am creating, and finally passing to the 'java' command. When I hard code the values in JAVA_OPTS rather than using variable expansion, the java process executes normally. When I use variable expansion, I get errors from the java executable. Here is the relevant portions of the script:
SERVER="-server"
MEM_OPTS="-Xms512m -Xmx1024m"
case "$1" in
start)
java "$SERVER" "$MEM_OPTS" $JAVA_OPTS \
-classpath "${JBOSS_CLASSPATH}" \
-Dorg.jboss.resolver.warning=true \
-Dsun.rmi.dgc.client.gcInterval=3600000 \
-Dsun.rmi.dgc.server.gcInterval=3600000 \
-Djboss.server.name=${SERVICE_NAME} \
-Djboss.server.base.dir=`dirname ${EC_APP_HOME}` \
-Djboss.server.base.url=file://`dirname ${EC_APP_HOME}` \
-Djboss.server.home.dir=${EC_APP_HOME} \
-Djboss.server.home.url=file://${EC_APP_HOME} \
org.jboss.Main >> out.log 2>&1 &
Executing this gives the following:
Invalid initial heap size: -Xms512m -Xmx1024m
Could not create the Java virtual machine.
However when I remove the variable expansion like so:
java "$SERVER" -Xms512m -Xmx1024m $JAVA_OPTS \
java executes no problems. As an aside, when I include "-server" in the MEM_OPTS var, I get the error "unrecognized option".
So obviously, there is something up with the variable expansion. I've hexdump'd the script, and made sure there are no extra characters in the string, and verified that I'm using Unix line endings. I've also reproduced the problem on two different linux machines, albeit both running the same version of ubuntu (one 32bit, the other 64bit).
EDIT: I get the same result with all forms of variable substitution: $MEM_OPTS, ${MEM_OPTS}, "${MEM_OPTS}"
Any ideas?
When you use "$MEM_OPTS", you're passing -Xms512m -Xmx1024m as a single option.
Try this instead:
java "$SERVER" $MEM_OPTS $JAVA_OPTS \
A good guide to variable substitution and quoting with examples: http://tldp.org/LDP/abs/html/varsubn.html
I am not 100% sure about the semantics of the quotes, but "$MEM_OPTS" may create a single argument "-Xms512m -Xmx1024m", whereas the JVM needs to see two seperate arguments. Can you try without the quotes?
java $SERVER $MEM_OPTS $JAVA_OPTS
think it should work if the quotes around $MEM_OPTS are removed, as the quotes tell bash to pass the expanded contents as a single token argument to execv()
My mistake - I was setting IFS to "\n" only in a script I sourced in, functions.sh. I was never resetting the IFS to "\n\t ", so the variables were not split on spaces.
Thanks for the responses!
It should be a simple matter of changing:
java "$SERVER" "$MEM_OPTS" $JAVA_OPTS \
to:
java "$SERVER" $MEM_OPTS $JAVA_OPTS \
so that the memory options are passed as two arguments.
But, since you say that doesn't work (?), please try the following.
A) Create a shell script fakejava.sh containing:
#!/usr/bin/bash
echo $#
while [[ $# -ne 0 ]] ; do
echo " [$1]"
done
(you may need to alter that first line if your bash is somewhere else: use which bash to figure out where).
B) Set its permissions correctly:
chmod 700 fakejava.sh
C) Replace your entire java command with:
./fakejava.sh "$SERVER" $MEM_OPTS $JAVA_OPTS xx
and see how many arguments there actually are. I get:
5
[-server]
[-arg1]
[-arg2]
[none]
[xx]
from the controlling script:
#!/usr/bin/bash
JAVA_OPTS="none"
SERVER="-server"
MEM_OPTS="-arg1 -arg2"
./fakejava.sh "$SERVER" $MEM_OPTS $JAVA_OPTS xx