I'm trying to run a pod-bootstrapping script (which basically runs a java program) after tomcat is started in the pod. My pod runs a single tomcat-based container. Here is the snippet that I'm working and re-working on:
- image: myreg/mydir/myimg:local
name: tomcat-adminapp
command: ["/bin/sh"]
args: ["-c", "$CATALINA_HOME/bin/startup.sh && /scripts/runUpg.sh"]
runUpg.sh script:
#!/bin/sh
ls -l $CATALINA_HOME/webapps/app/WEB-INF/lib/
chmod 755 $CATALINA_HOME/webapps/app/WEB-INF/lib/*
java -classpath "$CATALINA_HOME/webapps/app/WEB-INF/lib/*" com.myclass.Upg <args>
tail -f /dev/nul
It is starting tomcat but my script execution fails. When I exec into the pod, I see the war is exploded, CATALINA_HOME is set and tomcat process is running. But I see following script errors in kubectl logs:
ls: cannot access '/userhome/tomcat/webapps/app/WEB-INF/lib/': No such file or directory chmod: cannot access '/userhome/tomcat/webapps/app/WEB-INF/lib/*': No such file or directory Error: Could not find or load main class com.myclass.Upg Caused by: java.lang.ClassNotFoundException: com.myclass.Upg
From the error I'm guessing the shell script might not be waiting for tomcat to finish its startup. I'm not sure why..
When I manually run the script from inside the pod, it runs fine.
Any pointers here are appreciated..
Update: I confirmed it is indeed the timing issue. When I use $CATALINA_HOME/bin/startup.sh && sleep 60 && /scripts/runUpg.sh
, the script seems to run fine. But I think this is hack-ish and not the right way to achieve a call to a class within the webapp.
Consider postStart hook to execute a script after the container is started.
sample reference
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
Some things look "suspicious" to me:
/userhome/tomcate/webapps/app/WEB-INF/lib
- shouldn't it be /user/home
? (its just a side note, I'll assume you've defined it correctly)
Real issue. I don't remember how exactly the tomcat scripts are defined but event without kubernetes you can try to run the tomcat startup script and immediately run something like ls
on the lib folder. The chances that the folder indeed won't exist and here is why (in my understanding, again):
Tomcat (as a standalone process) was written in a way that it will run "always" but in some points of time you could place "WARs" into webapps folder and it will extract the WAR and start the appliaction. Then you could later, again, place another war and so forth. In other words, Lifecycle of Tomcat as a process is not bound to the lifecycle of the application
The startup process of the tomcat itself is supposed to read the configurations, create HTTP connector to listen on port 8080 or something and thats it, after this point the script is done, the tomcat is started.
In terms of solution:
Don't rely on tomcat to create a classpath of your process for you, its just wrong. Instead you can:
com.myclass.Upg
process should be self-contained (meaning contain its own dependencies).