Is there any way to get at Java internal properties, such as sun.arch.data.model , from a command line on windows? I need a command to put in a batch script that will detect the java architecture type: 32-bit or 64-bit .
If you are using Sun's VM (and I would suppose other VMs have similar details in their version information), you can check for the string "64-Bit" in the output of "java -version":
java -version 2>&1 | find "64-Bit" >nul:
if errorlevel 1 (
echo 32-Bit
) else (
echo 64-Bit
)
jarnbjo's script is for Windows. In Unix shell, you can use the following script.
#!/bin/sh
BIT=`java -version 2>&1`
case "$BIT" in
*64-Bit*)
echo "64-Bit"
;;
*)
echo "32-Bit"
;;
esac
Here is a prewritten property dump program for you: linky
If you install Groovy you can use
groovy -e "System.properties.each{println it}"
for all properties, and
groovy -e "println System.properties['sun.arch.data.model']"
for specific properties.
Installing Groovy is as easy as extracting a zip and add to path.
Related
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"
I am writing a bash script that should execute some Java application that needs a specific classpath.
Further, this script should be executable on both, Ubuntu & Windows (Cygwin).
The problem: The seperator on Windows is ";" and the seperator on Ubuntu is ":". This results in java -cp A.jar;B.jar Main on Windows (also when using cygwin, because it's using Windows' java) and java -cp A.jar:B.jar Main on Ubuntu.
The question: How to detect in the bash script which underlying operating system is running / which java classpath seperator to use?
A naive (but quick to implement) approach: run uname -a first and push that into a variable. Then check if that output contains "Ubuntu".
If so, you should be using the ":" as separator; otherwise ";" should do.
And if you want to be prepared for other platforms in the future; instead of doing a simple if/else; you might want to check what uname -a has to say on cygwin; to setup some $SEPARATOR_CHAR variable using a bash switch statement.
Just to provide the final solution:
I just tested uname -s on Ubuntu, Mac, and Windows running cygwin and came up with following script:
if [ "$(uname)" == "Darwin" ]; then
# Do something under Mac OS X platform
SEP=":"
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
# Do something under GNU/Linux platform
SEP=":"
elif [ "$(expr substr $(uname -s) 1 6)" == "CYGWIN" ]; then
# Do something under Windows NT platform
SEP=";"
fi
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"
I have the following simple script (test.sh):
#!/bin/bash
tail -f /var/log/dmesg > /tmp/output.log &
echo "THE END"
exit 0
After calling this test.sh script from a java program (remotely under ssh), the java console (eclipse) stay locked. Then,
1) If I manually kill the "tail -f /var/log/dmesg > /tmp/output.log" process in the server, the console unlocks and I get the "THE END" message in the console.
2) If I remove the "tail -f /var/log/dmesg > /tmp/output.log" from the script and run the java app, no lock happens and I get the "THE END" message in the console.
Is there anyone to run tail -f in bg through test.sh, and continue with the java app flow?
Try with nohup:
nohup tail -f /var/log/dmesg > /tmp/output.log &
SSH will sometimes wait for all processes to close the tty before exiting. nohup will set stdin to /dev/null and stdout/stderr to a file, so SSH can exit immediately (flushing any buffers that may be keeping "THE END" from showing).
There may also be some pitfalls on the Java side when it comes to running Unix system commands via Java. For example, if the standard I/O streams (stdout, stderr, stdin) of Unix-based operating systems are not being read in Java Threads, Unix system calls may unexpectedly block or even deadlock (for more detailed information on this topic please see Java exec - execute system processes with Java ProcessBuilder and Process (part 3) (2012).
Try the following Java sample code based on ThreadedStreamHandler.java, SystemCommandExecutor.java and ProcessBuilderExample.java that runs commands.add("ssh localhost /tmp/test.sh"); (it worked for me using the latest Eclipse Java EE IDE for Web Developers - Mac OS X version):
# References:
#
# - "Java exec - execute system processes with Java ProcessBuilder and Process (part 3)" (2012),
# http://alvinalexander.com/java/java-exec-processbuilder-process-3
#
# - "Running system commands in Java applications" (2012),
# http://alvinalexander.com/java/edu/pj/pj010016
#
# - "When Runtime.exec() won't: Navigate yourself around pitfalls related to the Runtime.exec() method" (2000),
# http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
mkdir -vp /tmp/com/devdaily/system
cd /tmp/com/devdaily/system
curl -LO http://alvinalexander.com/java/edu/java-exec/ProcessBuilderExample.java
curl -LO http://alvinalexander.com/java/edu/java-exec/SystemCommandExecutor.java
curl -LO http://alvinalexander.com/java/edu/java-exec/ThreadedStreamHandler.java
cd ../../..
# create commands.add("ssh localhost /tmp/test.sh");
printf '%s\n' 'H' ',s|ls -l.*tmp|ssh localhost /tmp/test.sh|' 'wq' |
ed -s com/devdaily/system/ProcessBuilderExample.java
echo '
#!/bin/bash
tail -f /private/var/log/system.log > /tmp/output.log &
echo "THE END"
exit 0
' > /tmp/test.sh
chmod +x /tmp/test.sh
javac com/devdaily/system/ProcessBuilderExample.java
java com/devdaily/system/ProcessBuilderExample
java -version
# java version "1.6.0_31"
# Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-10M3646)
# Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)
# Eclipse Java EE IDE for Web Developers (Mac OS X version).
# Version: Juno Service Release 2
# Build id: 20130225-0426
#
# use the following menu sequences:
# Window --> Show View --> Console
# Run --> External Tools --> External Tools Configuration... --> Program (double-click) --> New_configuration
# Location: /usr/bin/java
# Working Directory: /tmp
# Arguments: com/devdaily/system/ProcessBuilderExample
Have a look at htis article, it describes main mistakes while working with processes. What you have to do is to add a Steam Gobbler - consumer of input streams, so that outer progrem not to stuck while writing to output, becouse of full buffer.
I'm trying to develop a bash build script for a Java project that will be run on Ubuntu and Fedora. Ubuntu uses the gcj compiler while Fedora uses IcedTea.
Both report their errors and warning in slightly different ways, and I want to ignore the warnings (I know, not generally a good idea, but some of the warnings are simply idiotic).
For gcj, I want to run:
javac *.java 2>&1 | grep -A 4 "error:"
but for IcedTea, I want to run:
javac *.java 2>&1 | grep -A 4 "error:\|errors\|.java:"
I'm still new to bash, so how would I write an if statement that would run one versus the other based upon the javac version?
Assuming your java and javac binaries match, and that icedtea is the special case.
#!/bin/bash
ERROR="error:"
java -version 2>&1 | grep -i icedtea > /dev/null
if [ $? -eq 0 ]; then
ERROR="error:\|errors\|.java:"
fi
javac *.java 2>&1 | grep -A 4 $ERROR
On my system, icedtea and sun have the same output for "javac -version", but not for "java -version".
Writing Java build scripts in bash (or any other shell language) has a number of problems:
scripts tend to be non-portable due to shell differences, different command locations, incompatible command options and so on ... even if you try to make the portable.
scripts cannot cope with dependencies (or at least not easily)
scripts cannot cope with recompiling only stuff that has changed
Instead, I suggest that you write a "build.xml" file and use the Ant build tool. Ant has the advantage of running on any build platform that runs Java, and of taking care of the vast majority of platform differences. It is sort of like a better "Make" designed specifically for building Java.
#!/bin/sh
JAVAC_VERSION="`java -version 2>&1 /dev/null | awk '/IcedTea/ {print $4}' | sed -e 's/[\(0-9]//g'`"
ICEDTEA="IcedTea"
if [ ${JAVAC_VERSION} = ${ICEDTEA} ]; then
javac *.java 2>&1 | grep -A 4 "error:\|errors\|.java:"
else
javac *.java 2>&1 | grep -A 4 "error:"
fi
exit 0
That should do it - if i understood your question correctly. How you get the version - im not quite sure of, but if my javac -version is incorrect just change it accordingly to your needs.