setenv.sh causing Tomcat7 to "fail" start - java

The problem is not as easy as it seems in the title.
I'm using a default Tomcat 7 package on Unbutu 14.04 LTS. When I have no "setenv.sh" in /usr/share/tomcat7/bin, it starts saying "OK" when I do :
$ sudo service tomcat7 start
* Starting Tomcat servlet engine tomcat7 [OK]
When I use the setenv.sh described below, it ALSO STARTS with no error in /var/lib/logs/catalina.out but the service is detected as "failed" when /etc/init.d/tomcat7 calls "start-stop-daemon --test" and concludes it's not running :
$ sudo service tomcat7 start
* Starting Tomcat servlet engine tomcat7 [fail]
What can I do about this ?
/usr/share/tomcat7/bin/setenv.sh :
#! /bin/sh
export JAVA_HOME="/home/linc/install/jdk1.7.0_75"
(...)
# Check for application specific parameters at startup
if [ -r "$CATALINA_BASE/bin/appenv.sh" ]; then
. "$CATALINA_BASE/bin/appenv.sh"
fi
There is an other problem, maybe related : when I check the process running after the start detected as "failed" (ps -ef | grep java), I can see all -D options added by setenv.sh, but I can't see the -D option added by "appenv.sh" (though setenv.sh and appenv.sh have exactly the same 755 rights).
Note : if I launch sudo /usr/share/tomcat7/bin/startup.sh, the setenv.sh doesn't cause any problem and appenv.sh is used.
EDIT : I may have found the cause but not the explanation : when I remove the declaration of JAVA_HOME, it uses the default jvm and the service start is detected as "OK", but when I specify the home of the default jvm , it fails again !
export JAVA_HOME="/usr/lib/jvm/java-8-oracle/jre"
or :
export JAVA_HOME="/usr/lib/jvm/java-8-oracle"
What is happening here ?

Here are the explanations.
The command testing wether the service is up or not excpects not only a PID but also a precise java binary :
start-stop-daemon --test --start --pidfile "$CATALINA_PID" \
--user $TOMCAT7_USER --exec "$JAVA_HOME/bin/java" \
>/dev/null;
This is run 2 times, one before "catalina.sh" (and setenv.sh) is run, one after.
The "standard" tomcat conf on ubuntu works like this : /etc/init.d/tomcat7 can be overrided by /etc/default/tomcat7 who can be overrided by catalina.sh (+ setenv.sh + appenv.sh).
So there are run with 2 different JAVA_HOME, first one with the one in /etc/default/tomcat7 or some auto-detected one, and second one with the one set in setenv.sh. This makes the start-stop-daemon test fail.
The solution would be to set JAVA_HOME twice, one in /etc/default/tomcat7 for the service launch, and one in setenv.sh in case some direct launch (via startup.sh in shell) needs to be done for test purpose, with some comments warning about the duplication.
About appenv.sh, the reason is CATALINA_BASE == CATLINA_HOME only when you start Tomcat from command line (startup.sh). When running Tomcat as a service CATALINA_BASE = /var/lib/tomcat7 while $CATALINA_HOME = /usr/share/tomcat7.
So putting setenv.sh (and appenv.sh) in /var/lib/tomcat7/bin/ instead of /usr/share/tomcat7/bin solve the problem.

Related

Permissions error running Java Timezone Updater JAR in Dockerfile

I have a fairly standard Java image with some dependencies added in that I'm writing this Dockerfile on top of. Here's where I'm having a problem in my Dockerfile:
RUN which java
RUN ["/usr/bin/java", "-jar", "tzupdater.jar", "-v", "-l"]
I thought that every Dockerfile command was run as root? But when I try to build from this Dockerfile, I'm running into this permissions issue which also happened in my local environment when I forgot to run this JAR as sudo:
$ docker build -t container-w-tz-update .
Uploading context 1.122 GB
Uploading context
Step 0 : FROM company/java-img-with-dependencies:1.0
---> 0101010101
...
Step 3 : RUN which java
---> Running in 0101010101
/usr/bin/java
---> 0101010101
Step 4 : RUN ["/usr/bin/java", "-jar", "tzupdater.jar", "-v", "-l"]
---> Running in 0101010101
java.vendor: Sun Microsystems Inc.
java.version: 1.6.0_45
tzupdater version 2.1.1-b01
Downloaded file to /tmp/tz.tmp/tzdata.tar.gz
Downloaded file to /tmp/tz.tmp/sha512hash
failed.
Cant rename {0} to {1}.
com.sun.tools.tzupdater.TzRuntimeException: com.sun.tools.tzupdater.TzRuntimeException: Cant rename {0} to {1}.
Caused by: com.sun.tools.tzupdater.TzRuntimeException: Cant rename {0} to {1}.
at com.sun.tools.tzupdater.TimezoneUpdater.update(TimezoneUpdater.java:301)
at com.sun.tools.tzupdater.TimezoneUpdater.run(TimezoneUpdater.java:249)
at com.sun.tools.tzupdater.TimezoneUpdater.main(TimezoneUpdater.java:643)
2017/04/05 22:20:23 The command [/usr/bin/java -jar tzupdater.jar -v -l] returned a non-zero code: 1
I was able to run this utility as sudo on my local with the exact same version of Java with no issues. When I tried to run it locally without sudo, I received the same error. Thoughts?
(This is more like a comment but the message length is beyond the comment limit, so I leave it here as an answer so that other people can maybe give more useful info based on what I've done.)
Seems it's really an unresolved issue, I reproduced your problem by image enoniccloud/java6 running with root user, I also tried docker run -it --privileged ... to run it manually but it does not help. I also tried jdk8 with base image alpine:3.3 but also failed with:
Downloaded file to /tmp/tz.tmp/sha512hash
Renaming /opt/jdk1.8.0_91/jre/lib/tzdb.dat to /opt/jdk1.8.0_91/jre/lib/tzdb.dat.tzdata2016a failed.
Cant rename {0} to {1}.
Validating for : tzdata2017b
Validation complete
JRE updated to version : tzdata2017b
I searched and the only info I found is as follows:
An open issue: https://github.com/docker/hub-feedback/issues/896
Related but not the same: https://forums.docker.com/t/update-docker-container-jre-to-set-timezone-correctly/24426
Before you find the root cause for this issue, I think an alternative way to build your image could be:
Download a JDK tarball for your platform
Untar it, setup JAVA_HOME and PATH, run java -jar tzupdater.jar -v -l on your host
Build your base image based on this updated JDK, ADD to image and setup environment variable like JAVA_HOME and PATH
Hope this could be helpful to you :-)
docker build will complete RUN steps as the last USER set in the Dockerfile.
To reset:
RUN whoami
USER root
RUN ["/usr/bin/java", "-jar", "tzupdater.jar", "-v", "-l"]
USER "whatever whoami reported"
I got a workaround for that. Adding some mv commands (that have no real effect) made it work:
FROM openjdk:7u211-jdk-alpine3.9
ADD tzupdater.jar tzupdater.jar
RUN mv /usr/lib/jvm/java-1.7-openjdk/jre/lib/zi /usr/lib/jvm/java-1.7-openjdk/jre/lib/zi.tzdata2018g && \
mv /usr/lib/jvm/java-1.7-openjdk/jre/lib/zi.tzdata2018g /usr/lib/jvm/java-1.7-openjdk/jre/lib/zi && \
java -jar tzupdater.jar -v -l https://.../tzdata-latest.tar.gz
I have no idea why it works, I got it by trial and error.
Notice the two mv commands do like mv a b && mv b a, so nothing really changes.
The names of the files (dirs, actually) used in the mv are the ones it outputs when it errors (before the workaround), so change it accordingly.

How I should fix java-path, in order to run tomcat?

I installed tomcat, set variables CATALINA_HOME=/opt/tomcat and CATALINA_BASE=/opt/tomcat. in terminal I entered command which java and got response /usr/bin/java. So how I understand this is path for JAVA_HOME. I set it. When I start tomcat in terminal with $CATALINA_HOME/bin/startup.sh I get response:
Using CATALINA_BASE: /opt/tomcat
Using CATALINA_HOME: /opt/tomcat
Using CATALINA_TMPDIR: /opt/tomcat/temp
Using JRE_HOME: /usr/bin/java
Using CLASSPATH: /opt/tomcat/bin/bootstrap.jar:/opt/tomcat/bin/tomcat-juli.jar
Tomcat started.
But when I check, I see that tomcat wasn't started and in logs I found:
/opt/tomcat/bin/catalina.sh: 1: eval: /usr/bin/java/bin/java: not found
I suppose,that something wrong with path to java. How can I fix it?
PS everyhing was performed in Ubuntu OS
I think you should point your JRE_HOME to the directory where your java is installed, not the executable java itself. An example would be
/usr/lib/jvm/java-7-oracle where that folder will contain the bin/java executable...
You can also edit the file ../bin/setclasspath.sh and have an entry
JAVA_HOME="##path of the java directory##"
This will make sure whenever you try to start the tomcat, the JAVA_HOME will be enforced.
When the tomcat is started it is searching for setenv.sh in Catalina home or base.
Quote from Catalina.sh:
# Do not set the variables in this script. Instead put them into a script
# setenv.sh in CATALINA_BASE/bin to keep your customizations separate.
#
# JAVA_HOME Must point at your Java Development Kit installation.
# Required to run the with the "debug" argument.
# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=
if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
. "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
. "$CATALINA_HOME/bin/setenv.sh"
fi
So best way to set JAVA_HOME in tomcat is through setenv.sh
create a file setenv.sh in $CATALINA_HOME folder
Add this line to it : "export JAVA_HOME=/usr/"
Make it executable : "chmod 750 setenv.sh"
Start the startup.sh script, it will start the tomcat.
Try to set up JAVA_HOME property in /etc/default/tomcat7:
JAVA_HOME=/usr/bin/java
This will force Tomcat to use JVM located under /usr/bin/java
For C shell (csh), edit the startup file (~/.cshrc):
set path=(/usr/local/jdk1.7.0/bin $path)
For bash, edit the startup file (~/.bashrc):
PATH=/usr/local/jdk1.7.0/bin:$PATH
export PATH
For ksh, the startup file is named by the environment variable, ENV. To set the path:
PATH=/usr/local/jdk1.7.0/bin:$PATH
export PATH
For sh, edit the profile file (~/.profile):
PATH=/usr/local/jdk1.7.0/bin:$PATH
export PATH
Then load the startup file and verify that the path is set by repeating the java command:
For C shell (csh):
% source ~/.cshrc<br>
% java -version
For ksh, bash, or sh:
% . /.profile<br>
% java -version
In Ubuntu
Set JAVA_HOME in .bashrc as export JAVA_HOME=/usr/lib/jvm/java-8-oracle/
and run . .bashrc then start tomcat server
This one solved my issue:
https://ubuntuforums.org/showthread.php?t=1018063
PS: I installed tomcat8 by apt-get instead of downloading the compressed tomcat file.

HOME environment variable not set in bash script

I have a Java program that spawns a bash script that calls another script. In that second script, I'm finding that the $HOME variable is not set. Here's the gist of it:
In Java:
Process p = new ProcessBuilder("bash", "-l", "/foo/a.sh").start();
// code to actually execute p
/foo/a.sh:
#!/bin/bash
/foo/b.sh
/foo/b.sh:
#!/bin/bash
echo "HOME=$HOME"
This echoes "HOME=". The eventual problem is that $HOME/bin is supposed to be added to my PATH in ~/.profile, but since that's not happening, a bunch of custom executables aren't being made accessible.
I worked around it by doing:
if [ -d ~/bin ] ; then
PATH=~/bin:"$PATH"
fi
And that works fine. But I guess I just want to understand why $HOME wasn't being set. It seems like $HOME and ~ should be largely equivalent, no? There's probably something I'm fundamentally missing about how this environment is getting set up.
I am running Ubuntu 12.04.5, if that makes a difference.
The evidence suggests that HOME is missing from the environment in which the Java app is running. Assuming that the app doesn't explicit unset HOME, the most likely reason is that the app is being started from some context other than a login by the user the app is running as.
It's correct that ~ and $HOME are similar. If HOME is present in the environment, even if it is set to the empty string, ~ will be replaced with $HOME. However, if HOME is not present in the environment, bash will attempt to find the home directory for the currently logged in user, and use that for ~.
eg.
$ bash -c 'echo ~'
/home/rici
$ HOME='Hello, world!' bash -c 'echo ~'
Hello, world!
$ HOME= bash -c 'echo ~'
$ (unset HOME; bash -c 'echo ~';)
/home/rici
Since your workaround requires the equivalent of the last scenario, I conclude that HOME has not been set, or has been unset.

tomcat7 wont run on startup

Tried everything but it just wont work, im running tomcat7 on an EC2 instance (amazon AWS). I can start up tomcat7 manually by starting startup.sh, but not automatically on startup. The error message I get in logs/catalina.out is the following:
/etc/apache-tomcat-7.0.32/bin/catalina.sh: 1: eval: /etc/jdk1.7.0_07/bin/java: not found
My enviroment variables are also setup properly:
echo $JAVA_HOME -> /etc/jdk1.7.0_07/bin/java
echo $PATH -> /usr/local/sbin:/usr/local/bin:/usr/sbin/:/usr/bin:/sbin:/bin:/usr/games:/etc/jdk1.7.0_07/bin
I can also type "java -version" in shell getting proper output, however "/etc/jdk1.7.0_07/bin/java -version" does not work and only returns "No such file or directory".
Im really not sure what to do now, feels like i tried everything, hope someone can help me!
Also the instance is running Ubuntu server 12.04.
Do sudo su vi /etc/bash.bashrc and copy following
JAVA_HOME=/etc/jdk1.7.0_07 //you have to only specify path until java dir not bin
export JAVA_HOME
PATH=$PATH:$JAVA_HOME/bin
export PATH
I do not particularly known about specifics of ubuntu+tomcat7 on EC2. So my answer could be missing a point a bit. It is given from generic ubuntu point of view.
Possibly things will be a bit easier to manage if you use apt-get to manage tomcat and java on ubuntu. In that case the tomcat will automatically started on start up. The commands below are tested on ubuntu 12.10, but also worked on some earlier version.
To install Java you need the following:
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java7-installer
If the first command fails, use the following:
sudo apt-get install software-properties-common
Then install tomcat7 using:
sudo apt-get install tomcat7
After that you need to tell tomcat to use installed java 7. For that purpose modify /etc/default/tomcat7 file either manually or using command like the following:
cat /etc/default/tomcat7 | sed 's/#JAVA_HOME=\/usr\/lib\/jvm\/openjdk-6-jdk/JAVA_HOME=\/usr\/lib\/jvm\/java-7-oracle/' >/tmp/tomcat7-updated
sudo cp /tmp/tomcat7-updated /etc/default/tomcat7
After that tomcat should load on start up. You just need to tune up ports and other configuration information. Note that this tomcat uses /var/lib/tomcat7/webapps/ to store web applications. You could also start or stop tomcat manually using the commands like the following:
sudo /etc/init.d/tomcat7 start
For automatic startup of tomcat, it should be started during booting time only.
For that you need to write a script which starts the tomcat and put this file in the etc/init.d or you can put it for different runlevels.
The hint for me was modifying the shell script file (set JAVA_HOME variable) and this resolved the issue.
The tomcat script file is generally under /etc/init.d/ directory

JAVA_HOME not found as Sudo

I have a bash script on a Linux box that runs a Jar file. When logged in as a regular user I don't have permission to run the script, but it prints the following log:
*INFO * Using JVM found at /opt/jdk6/bin/java
When I try to use the script with Sudo though, it gives:
*ERROR* Unable to locate java, please make sure java is installed and JAVA_HOME set
I've set JAVA_HOME to the same path above — can see it with echo $JAVA_HOME & it's also set as an option within the script. I'm happy that the script isn't the issue — it's a default CQ5 control script & I'm using it on dozens of other boxes without issue. Just unsure what I'm doing wrong above & presume it's something I'm missing re Linux set-up?
When I run the sudo command, does it have access to the JAVA_HOME that I set up as myself?
By default, sudo will cleanup the environment of the spawned commands. Pass -E to keep it:
sudo -E env
Compare to:
sudo env
"sudo -E " didn't solve the problem when JAVA_HOME was not exported. And when it was exported, "sudo " without -E works the same.
So you can add export JAVA_HOME=.../jdk<version> in your .bash_profile and .bashrc file.
In case you wondered what's the difference of .bash_profile and .bashrc, .bash_profile is executed upon login (e.g., show some diagnostic/welcome information). .bash_rc is executed when you open a new terminal (e.g., shift-ctrl-T).
In order to run some commands for both cases, you can put it in .bashrc file, and let .bash_profile source .bashrc:
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
You could always just pass it to java explicitly like this:
sudo java -Djava.home=$JAVA_HOME Test

Categories