I like to use two scripts for running and managing the lifecycle of server applications: a
start script and an
start script does the actual job of launching the application. In the case of Scala or Java it fires up the JVM and adds all the necessary arguments (memory, GC, etc.). It should also provide the basic configuration for your application: main entry point, classpath, config file, logging config file, etc. You should be able to easily run the application by simply launching the
start script; however this is not something you’re most likely ever do to – for that you have the
init.d script is used to control the application’s process state and lifecycle: start and stop it, check whether it’s running, and restart it if necessary. It should also manage the application’s
pid file. It could be used for event monitoring, like letting an external system know that the service’s state has changed. The
init.d script doesn’t interact with the app itself, but rather with its
start script. This allows you to decouple application specific configuration from the lifecycle and state of the operating system process.
Below are the two scripts that I use. These are actually jinja2 templates that I use in conjunction with Ansible to deploy multiple services. They assume that your application is deployed as a thin jar in
BIN_DIR, with all of its dependencies in the same directory (as can be achieved by using standalone Ivy, Maven and its
dependency:get plugin, or simply by exploding a fat jar downloaded on the server).
(Gist found here)
(For application configuration I’m using Typesafe config with the
config.file parameter, and Logback with the
logback.configurationFile parameter for logging, but that shouldn’t matter at all. Customize as needed.)
I usually like to place the
start script right next to the
BIN_DIR in a
script directory. Here’s my typical structure:
All of these pieces are put in-place by the CM tool. Launching the
start script will run the application interactively in the logged in session, displaying
stdout in the terminal. This could be useful for debugging, but should generally be avoided – you should start the app from the
(Gist found here)
This script is a lot more complicated. Let’s break it down:
- You would normally put this script in
- The script accepts the following commands:
START_SCRIPTshould be the location of the
PID_FILEis where you want your
pidfile saved, usually:
- The script is intelligent enough not to let you start two instances of the app if it’s already running.
- Standard script exit codes:
0– program is running or service is OK
1– program is dead and /var/run pid file exists
3– program is not running
- Running each of the commands will output a colored status message with the result. For example:
The combination of these two scripts offers a robust way to manage the lifecycle of the app. I think they provide a good separation of concerns, and allow the
init.d script to be reusable for multiple types of applications, provided that they have a
start script. Only the
start script intimately knows the app and that it’s is JVM-based, and it does not bother itself with environment concerns like process ids and such.
If you’re interested in the rest of the deployment code I use for such server apps you can check out this Ansible role.
Have a comment or a suggestion for a better way to do any of this? Please let me know!