Java Startup Scripts on Mac OS X
How to Setup a Java Startup Script on Mac OS X ∞
This page describes how a Java Application can be automatically started and shutdown at boot and shutdown time like a Windows Service or Linux Run Level Service. This makes it possible to run application servers, web containers, databases etc in the background and have the available for as long as the box is up and running even if nobody is logged in.
On Mac OS X this works similar to Linux even though its features are more limited. The challenge with Java is that most script can only start a JVM and have problems to shut it down properly. A good solution is provided by the Java Service Wrapper which not only works for Mac but also Windows, Linux and more. It uses native code to control the JVM and also to monitor the JVM so that it can be restarted if it fails and to wait for the JVM to exit when shut down. For example the JBoss scripts are not waiting for the JVM to stop before the script returns and it also cannot handle multiple instances at the same time out of the box.
These are the steps for complete happiness using JBoss as the example:
- Download Java Service Wrapper (for your environment) and extract it. The question of 32-bit vs. 64-bit is with respect to the Java version. For example my MacBook Pro has a 64-bit Java version whereas my Mac OS X server only has a 32-bit version (go figure). In doubt download both version and try it out. JWS will tell you if the version don’t match.
-
Put these files into the the
/bin directory:- <JWS Extract Dir>/bin/wrapper
- <JWS Extract Dir>/lib/wrapper.jar
- <JWS Extract Dir>/lib/libwrapper.*
- <JWS Extract Dir>/src/conf/wrapper.conf.in
- <JWS Extract Dir>/src/bin/sh.script.in
- Rename and edit the wrapper.conf.in and sh.script.in file
- Create as root (sudo) a directory called: /Library/StartupItems/
- Create as root a file called: /Library/StartupItems/<Service Name>/<Service Name> and make it executable
-
Create as root a file called: /Library/StartupItems/
/StartupParameters.plist
The startup script file should be renamed to something more meaningful like for example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
wrapper.java.command=java wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp wrapper.java.classpath.1=./wrapper.jar wrapper.java.classpath.2=./run.jar wrapper.java.library.path.1=. wrapper.java.additional.1=-Dsun.rmi.dgc.client.gcInterval=3600000 wrapper.java.additional.2=-Dsun.rmi.dgc.server.gcInterval=3600000 wrapper.java.additional.3=-Djava.endorsed.dirs=../lib/endorsed wrapper.java.additional.4=-Djava.awt.headless=true wrapper.java.additional.5=-Dfile.encoding=UTF-8 wrapper.java.initmemory=512 wrapper.java.maxmemory=1024 wrapper.app.parameter.1=org.jboss.Main wrapper.app.parameter.2=-c wrapper.app.parameter.3=madplanet wrapper.app.parameter.4=-b wrapper.app.parameter.5=127.0.0.1 wrapper.console.format=PM wrapper.console.loglevel=INFO wrapper.logfile=./wrapper.log wrapper.logfile.format=LPTM |
The first 3 lines are fixed. The second classpath item is what loads JBoss. The Java parameter afterwards are what the JBoss scripts gives to Java when it starts up. I would suggest you use echo … on this line to see the startup parameters and then add one by one. The memory sizes depends on the application and your environment. The JBoss (app) parameters are also taken from the startup script. Exception the first one the are handed to the run.sh script. Finally there are the properties for the logging. After creating the startup items environment we have to put the code in place that executes the JWS script in the JBoss bin directory. This could look like this (keep in mind that mpc.jws.startup.sh is my startup script name):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#!/bin/sh . /etc/rc.common ## # Start J2EE App server ## StartService() { if [ "${JBOSS:=-NO-}" = "-YES-" ]; then ConsoleMessage "Starting JBoss" cd /Java/jboss/bin ./mpc.jws.startup.sh start fi } StopService() { cd /Java/jboss/bin ./mpc.jws.startup.sh stop } RestartService() { if [ "${JBOSS:=-NO-}" = "-YES-" ]; then ConsoleMessage "Retarting JBoss" cd /Java/jboss/bin ./mpc.jws.startup.sh stop ./mpc.jws.startup.sh start else cd /Java/jboss/bin ./mpc.jws.startup.sh stop fi } RunService "$1" |
Finally we have to edit the StartupParameters.plist file which looks like this:
1 2 3 4 5 6 7 8 9 10 11 |
{ Description ="JBoss App Server"; Provides =("JBoss"); Requires =("Resolver"); Preference ="Late"; Messages = { start ="Starting JBoss"; stop ="Stopping JBoss"; }; } |
The description is not important. The provides must match the service name (as far as I know). The rest was given to me so I can’t explain them any further.
Eventually we want to test that and this done with: sudo /sbin/SystemStarter start JBoss. To stop just replace start with stop.
Attention: In Mac OS X the start or stop parameter comes first unlike as in Linux.
Finally after you bounce the box the JBoss should be fired up and running right from the start. To debug the issue please use -v or -d option on the SytemStarter (or both), consult the JWS log file (in the /bin directory) and also the system log file.
Have fun – Andy