Running tomcat as a systemd unit

Linux

In a previous blog (see What is systemd), I talked about the new init system that most linux distributions are switching to. You can go read that one first if some of the things we talk about here are not making much sense.
Centos 7 our OS of choice comes with Tomcat 7.0.57. To take advantage of all the improvements and bug fixings done lately we wanted to have the latest version of Tomcat 7 installed on our system. (version 7.0.65 at the moment of writing this).

We downloaded this version, installed it, setup our applications, etc. Everything went smooth. There was one thing we started missing once we migrate to our new setup. The ability to run Tomcat at system boot, and the ability to just use systemd’s main command systemctl to start/stop/status etc.

So this is what we did to have downloaded Tomcat7 instance controlled via systemd.
First we created a new systemd service unit file "/etc/systemd/system/tomcat7.service". A systemd’s “service unit” describes how to manage a service or application on the server. This will include how to start or stop the service, under which circumstances it should be automatically started, and the dependency and ordering information for related software.
The available unit files for systemd can be seen in /usr/lib/systemd/system/ and /etc/systemd/system/ (the latter takes precedence). Notice that our new tomcat7 unit file is located in one of these special folders.

The list of installed unit files in your system can be seen using the following command. At the end of the article your list will include a new one called “tomcat.service”

[user@machine ~]$ systemctl list-unit-files

Here is the content of our tomcat7.service file

[user@machine ~]$ cat /etc/systemd/system/tomcat7.service
[Unit]
Description=Apache Tomcat 7 Servlet Container
After=syslog.target network.target
[Service]
User=apache
Group=apache
Type=forking
Environment=CATALINA_PID=/var/run/tomcat.pid
Environment=CATALINA_HOME=/opt/apache-tomcat-7.0.65
Environment=CATALINA_BASE=/opt/apache-tomcat-7.0.65
ExecStart=/opt/apache-tomcat-7.0.65/bin/startup.sh
ExecStop=/opt/apache-tomcat-7.0.65/bin/shutdown.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target

Let’s explain some of the content of this file. First of all, the syntax: the content is organized in sections, which are denoted by a pair of square brackets with the section name (case sensitive) enclosed within. Each section extends until the beginning of the subsequent section or until the end of the file. So, in our case we have 3 sections: Unit, Service and Install; Within these sections, unit behavior and metadata is defined through the use of simple directives using a key-value format with assignment indicated by an equal sign. If a ceratin pair is not specified than, the systemd’s default value for that specific key is going to be used.

The [Unit] section is generally used for defining metadata for the unit and configuring the relationship of the unit to other units. In here, first we are setting the unit description, see Description= directive.
The units listed in the After= directive will be started before starting the current unit. So, in our example we are making sure that the syslog and network targets are started before the tomcat7 service. This directive does not imply a dependency relationship (like the “Requires=” or “Wants=” does).

The [Service] section is used to provide configuration that is only applicable for services. Here we specify the OS user and group to be used as owner of the process spawned (see User= and Group= pairs). The Type= directive being used is “forking”, which means the service forks a child process, exiting the parent process almost immediately. This tells systemd that the process is still running even though the parent exited.
ExecStart= specifies the full path of the command to be executed to start tomcat, while ExecStop= specifies the full path of the command to be executed to stop tomcat. (If this is not given, the process will be killed immediately when the service is stopped.)
Restart= This indicates the circumstances under which systemd will attempt to automatically restart the service. This can be set to values like “always”, “on-success”, “on-failure”, “on-abnormal”, “on-abort”, or “on-watchdog”. These will trigger a restart according to the way that the service was stopped.
systemd has Environment directive which sets environment variables for executed processes. In our case we set the Tomcat’s CATALINA_PID, CATALINA_HOME and CATALINA_BASE.

The WantedBy= directive in the [Install] section is the most common way to specify how a unit should be enabled. Specifying the multi-user.target is the systemd equivalent of runlevel 3, which is a multi-user system that boots to a console, not a GUI.

After having this tomcat7.service file in place you have to notify systemd that a new name.service file exists by executing the following command as root:

[user@machine ~]$ systemctl daemon-reload

Once this is done you can use systemctl to start, stop or enable tomcat7 service.

[user@machine ~]$ systemctl start name.service
[user@machine ~]$ systemctl stop name.service

The output of our enable command is:

[user@machine ~]$ $ sudo systemctl enable tomcat7.service
Created symlink from /etc/systemd/system/multi-user.target.wants/tomcat7.service to /etc/systemd/system/tomcat7.service.

Enabling an unit means it will be started on system bootup, Just to test this is really happening, we restarted our machine and we checked the status of our new tomcat7.service

[user@machine ~]$ $ sudo systemctl status tomcat7.service
tomcat7.service - Apache Tomcat 7 Servlet Container
Loaded: loaded (/etc/systemd/system/tomcat7.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2016-01-10 10:30:44 EST; 1min 48s ago
Process: 797 ExecStart=/opt/apache-tomcat-7.0.65/bin/startup.sh (code=exited, status=0/SUCCESS)
Main PID: 822 (java)
CGroup: /system.slice/tomcat7.service
└─822 java -Djava.util.logging.config.file=/opt/apache-tomcat-7.0.65/conf/logging.properties -Djava.util....

Jan 10 10:30:44 staging-ods systemd[1]: Starting Apache Tomcat 7 Servlet Container...
Jan 10 10:30:44 staging-ods systemd[1]: Started Apache Tomcat 7 Servlet Container.

Great success! We’re done.