Running Different Bash Commands Based on Java Version - java

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.

Related

Why my java process on Linux OS did not show -classpath in java command when I input "ps -ef | grep java"?

I have this issue about java command when I input the following shell command "ps -ef | grep java".
And I got following commands which shows two java processes
the first process is like "java -Dxxx org.apache.hadoop.hdfs.server.namenode.NameNode" which does not specify the -classpath option. this command is confusing me a lot I don't know how it can find the class of "org.apache.hadoop.hdfs.server.namenode.NameNode" and other classes or jars that it depends on
the second process is like "java -Dxxx -classpath xxx.jar org.apache.hadoop.yarn.server.resourcemanager.ResourceManager" which make senses to me what a noraml java command should be like.
Can anyone help me to explain why the first command does not have the classpath?
//first process
root 4116 1 0 Jan30 ? 00:07:55 /root/jdk1.8.0_181/bin/java -Dproc_namenode -Xmx1000m -Djava.net.preferIPv4Stack=true -Dhadoop.log.dir=/root/hadoop-2.8.5/logs -Dhadoop.log.file=hadoop.log -Dhadoop.home.dir=/root/hadoop-2.8.5 -Dhadoop.id.str=root -Dhadoop.root.logger=INFO,console -Djava.library.path=/root/hadoop-2.8.5/lib/native -Dhadoop.policy.file=hadoop-policy.xml -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Stack=true -Dhadoop.log.dir=/root/hadoop-2.8.5/logs -Dhadoop.log.file=hadoop-root-namenode-hdfs01.log -Dhadoop.home.dir=/root/hadoop-2.8.5 -Dhadoop.id.str=root -Dhadoop.root.logger=INFO,RFA -Djava.library.path=/root/hadoop-2.8.5/lib/native -Dhadoop.policy.file=hadoop-policy.xml -Djava.net.preferIPv4Stack=true -Dhadoop.security.logger=INFO,RFAS -Dhdfs.audit.logger=INFO,NullAppender -Dhadoop.security.logger=INFO,RFAS -Dhdfs.audit.logger=INFO,NullAppender -Dhadoop.security.logger=INFO,RFAS -Dhdfs.audit.logger=INFO,NullAppender -Dhadoop.security.logger=INFO,RFAS org.apache.hadoop.hdfs.server.namenode.NameNode
//second process
root 4595 1 0 Jan30 pts/0 00:28:38 /root/jdk1.8.0_181/bin/java -Dproc_resourcemanager -Xmx1000m -Dhadoop.log.dir=/root/hadoop-2.8.5/logs -Dyarn.log.dir=/root/hadoop-2.8.5/logs -Dhadoop.log.file=yarn-root-resourcemanager-hdfs01.log -Dyarn.log.file=yarn-root-resourcemanager-hdfs01.log -Dyarn.home.dir= -Dyarn.id.str=root -Dhadoop.root.logger=INFO,RFA -Dyarn.root.logger=INFO,RFA -Djava.library.path=/root/hadoop-2.8.5/lib/native -Dyarn.policy.file=hadoop-policy.xml -Dhadoop.log.dir=/root/hadoop-2.8.5/logs -Dyarn.log.dir=/root/hadoop-2.8.5/logs -Dhadoop.log.file=yarn-root-resourcemanager-hdfs01.log -Dyarn.log.file=yarn-root-resourcemanager-hdfs01.log -Dyarn.home.dir=/root/hadoop-2.8.5 -Dhadoop.home.dir=/root/hadoop-2.8.5 -Dhadoop.root.logger=INFO,RFA -Dyarn.root.logger=INFO,RFA -Djava.library.path=/root/hadoop-2.8.5/lib/native -classpath /root/hadoop-2.8.5/etc/hadoop:/root/hadoop-2.8.5/etc/hadoop:/root/hadoop-2.8.5/etc/hadoop:/root/hadoop-2.8.5/share/hadoop/common/lib/*:/root/hadoop-2.8.5/share/hadoop/common/*:/root/hadoop-2.8.5/share/hadoop/hdfs:/root/hadoop-2.8.5/share/hadoop/hdfs/lib/*:/root/hadoop-2.8.5/share/hadoop/hdfs/*:/root/hadoop-2.8.5/share/hadoop/yarn/lib/*:/root/hadoop-2.8.5/share/hadoop/yarn/*:/root/hadoop-2.8.5/share/hadoop/mapreduce/lib/*:/root/hadoop-2.8.5/share/hadoop/mapreduce/*:/root/hadoop-2.8.5/contrib/capacity-scheduler/*.jar:/root/hadoop-2.8.5/contrib/capacity-scheduler/*.jar:/root/hadoop-2.8.5/contrib/capacity-scheduler/*.jar:/root/hadoop-2.8.5/share/hadoop/yarn/*:/root/hadoop-2.8.5/share/hadoop/yarn/lib/*:/root/hadoop-2.8.5/etc/hadoop/rm-config/log4j.properties org.apache.hadoop.yarn.server.resourcemanager.ResourceManager
The scripts run export CLASSPATH=$(hadoop classpath) or look under $HADOOP_HOME for jars.
-classpath isn't required Java parameter
You can also use jps to see running Java processes, which is what the Hadoop documentation suggests

bash - at refusing to execute script?

Let's say I have a script to start some java stuff
start.sh
myStuff=10.0.0.13
port=11212
servers=(10.0.0.9 10.0.0.10 10.0.0.11 10.0.0.12 10.0.0.14)
T=$1
R=$2
nohup java -jar myJar.jar -l ${myStuff} -p ${port} -t $T -r $R -m "${servers[#]/%/:11212}" &
If I start the script manually
./start.sh 64 1
for example, everything works as it should
now
echo "nohup ./start.sh 64 1" | at now
however, does nothing.
Why?
I've started similar scripts like this before (none that called java, though) and I can't seem to figure out how they differ.
EDIT
well, not quite nothing, the job DOES get scheduled and does disappear from the atq, but the jar is not started and there is no nohup.out anywhere.
EDIT 2
note that
echo "nohup ./start.sh 64 1 > help &" | at now
does create a help file (not a nohup.out file, though) but it's empty.
EDIT 3
note that changing the start.sh such that the path to the java binary is hardcoded:
nohup /usr/lib/jvm/java-1.7.0-openjdk-amd64/bin/java -jar myJar.jar -l ${myStuff} -p ${port} -t $T -r $R -m "${servers[#]/%/:11212}" &
doesn't help either.
EDIT 4
echo "nohup java -version > help &" | at now
creates an empty help file (but no nohup.out).
Whereas
echo "nohup java -version > help 2>&1 &" | at now
will print
java version "1.7.0_111"
OpenJDK Runtime Environment (IcedTea 2.6.7) (7u111-2.6.7-0ubuntu0.14.04.3)
OpenJDK 64-Bit Server VM (build 24.111-b01, mixed mode)
into the help file (and not create a nohup.out file either).
EDIT 5
getting rid of the nohup, i.e.
java -jar myJar.jar ...
and then
echo "./start.sh 64 1" | at now
doesn't change anything.

How to create a script to restart a JAR file and get output in a terminal?

I have used the following scripting for start and stop a jar file.
**start.sh**
#!/bin/bash
nohup nice java -jar Server.jar > ./Server.out 2>&1 &
**stop.sh**
#!/bin/bash
kill `ps -ef | grep Server.jar | grep -v grep | awk '{ print $2 }'`
Now I want to merge both scripts and create a new restart script. I also want this script output in a terminal instead of a text file(Server.out).
Would appreciate any kind of input/help.
You can either put the commands of the two sripts after each other (kill first, java second) or just call the two scipts in the appropriate order.
The idea is that restart is basically equivalent to killing the current running version and starting a new one.
To avoid the output to a file, remove the > ./Server.out part.
Edit: removed note about removing the redirection part as I misread the grep part of the kill script
Update: Missed the nohup part of the script: with nohup you need to redirect output to a file, because the process is detached from the terminal (see documentation). If you do want to see the output in the terminal, remove nohup as well as the redirection to the file

How to change/assign process name of java .jar

I'm running Minecraft under Linux, which involves running an executable .jar file. This means it shows up as "java" under ps, rather than "minecraft". I would like to assign it the process name "minecraft".
Looking around, I found the following tip for assigning a process name via bash:
how to change the name of a Java application process?
exec -a goodname java ...
I usually run with:
java -cp ~/Games/Minecraft/Minecraft.jar net.minecraft.LauncherFrame
So tried make a bash script:
#!/bin/bash
exec -a minecraft java -cp ~/Games/Minecraft/Minecraft.jar net.minecraft.LauncherFrame
But when I run this, it still shows up as "java" under the ps command.
What am I doing wrong?
It works for me. I haven't tested with java, but I tested with sleep:
victor#vz:~$ exec -a minecraft sleep 1m &
[1] 3858
victor#vz:~$ ps x | grep mine
3858 pts/2 S 0:00 minecraft 1m
3860 pts/2 S+ 0:00 grep --color=auto mine
victor#vz:~$
However, this seems to be merely a cosmetic change as far as I can tell by the documentation:
victor#vz:~$ help exec exec: exec
[-cl] [-a name] [command [arguments
...]] [redirection ...]
Replace the shell with the given command.
Execute COMMAND, replacing this shell with the specified program.
ARGUMENTS become the arguments to COMMAND. If COMMAND is not specified,
any redirections take effect in the current shell.
Options:
-a name pass NAME as the zeroth argument to COMMAND
In reference to OP's comment to this answer: I just tested it on a remote machine with java as well:
victorz#exa:~$ javac test.java # spits out an Administrator.class file among others
victorz#exa:~$ exec -a minecraft java Administrator &
[1] 13142
victorz#exa:~$ ps x | grep mine
13142 pts/1 Sl 0:00 minecraft Administrator
13161 pts/1 S+ 0:00 grep --color=auto mine
victorz#exa:~$
Maybe you are not using the x switch to ps? I get no match unless I use the x switch.

How do I detect 64-bit Java from the command line?

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.

Categories