Skip to content

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:

  1. 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.
  2. Put these files into the the /bin directory:

    1. <JWS Extract Dir>/bin/wrapper
    2. <JWS Extract Dir>/lib/wrapper.jar
    3. <JWS Extract Dir>/lib/libwrapper.*
    4. <JWS Extract Dir>/src/conf/wrapper.conf.in
    5. <JWS Extract Dir>/src/bin/sh.script.in
  3. Rename and edit the wrapper.conf.in and sh.script.in file
  4. Create as root (sudo) a directory called: /Library/StartupItems/
  5. Create as root a file called: /Library/StartupItems/<Service Name>/<Service Name> and make it executable
  6. Create as root a file called: /Library/StartupItems//StartupParameters.plist

The startup script file should be renamed to something more meaningful like for example: .jws.startup.sh. At the end the only important thing is that is must be made executable and accessible to root so that it can be fired up while booting. The only thing that we probably need to edit in this file is to adjust for the wrapper configuration file name. After that we have to rename the wrapper.conf.in file to a better name like for example: .wrapper.conf. Then we edit the content to something like this (keep in mind this is for JBoss application server and Jetty already contains the configuration file):

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