33

The Tomcat documentation describes the process of compiling and installing JSVC which can be used to run Tomcat as a daemon. As per my understanding, JSVC has two benefits:

  1. It launches as root allowing for the use of a privileged port (like 80 or 443).
  2. It creates a "controller process" which will monitor a "controlled process" (the main Java thread) and restart the process on failure.

I've been learning systemd, including the service unit configuration. Based on my limited understanding, systemd is able to perform the same tasks as JSVC if I set User=tomcat (using the desired username) and Restart=on-failure in my tomcat.service configuration file.

Using JSVC, I would expect tomcat.service to look something like this:

[Unit]
Description=Apache Tomcat
After=network.target

[Service]
Environment=CATALINA_PID=/var/run/tomcat.pid
Environment=JAVA_HOME=/path/to/java
Environment=CATALINA_HOME=/opt/tomcat
...

ExecStart=/opt/tomcat/bin/jsvc \
    -Dcatalina.home=${CATALINA_HOME} \
    -user tomcat \
    -java-home ${JAVA_HOME} \
    -pidfile ${CATALINA_PID} \
    ...
    org.apache.catalina.startup.Bootstrap

ExecStop=/opt/tomcat/bin/jsvc \
    -pidfile ${CATALINA_PID} \
    ...
    -stop \
    org.apache.catalina.startup.Bootstrap

[Install]
WantedBy=multi-user.target

Using systemd, I would expect tomcat.service to look something like this:

[Unit]
Description=Apache Tomcat
After=network.target

[Service]
Type=forking  
PIDFile=/var/run/tomcat.pid
User=tomcat
Group=tomcat
Environment=JAVA_HOME=/path/to/java
Environment=CATALINA_HOME=/opt/tomcat
...

Restart=on-failure

ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh

[Install]
WantedBy=multi-user.target

My preference is using just systemd as it's already there and I have to (should) use it anyway. I am however uncertain as to whether or not I will be missing any benefit of using JSVC that I am overlooking.

What can be achieved by JSVC that cannot be achieved by systemd if I want to run Tomcat as a daemon?

Also, if systemd is able to perform the same tasks as JSVC as well as JSVC, I'd also like to ask for any configuration tips you may offer to best achieve the benefits of JSVC using just systemd.

3 Answers3

25

In general, most of the functionality provided by jsvc is provided by systemd, with the exception of opening of privileged ports (see below). If possible, it is a very good idea to switch to using systemd functionality directly, since things become simpler and more efficient.

Your unit file looks mostly OK, with the exception of

ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh

This part looks like another wrapper which can be replaced with a direct to java -jar ....

Opening privileged sockets

Under Systemd this is usually done through socket activation. Systemd opens the socket and hands it to the daemon as an open file descriptor (like stdin, stdout, stderr).

The daemon can then be started as unprivileged user, and does not drop privileges itself. The daemon has to support this, and instead of opening the socket by itself, it should use the one it was given. Under Java this is made very problematic by the lack of support in the Java stdlib.

AFAIK, tomcat does not support socket activation, so if you want to use an privileged port and run the daemon under an unprivileged user, jsvc might still be necessary.

slm
  • 15,396
  • 12
  • 109
  • 124
zbyszek
  • 5,105
  • 1
  • 27
  • 22
  • 1
    I would not use the startup.sh script but make sure to start the java command line directly. This results in less processes and the systemd can directly track the JVM process (for respawn). – eckes Mar 08 '15 at 23:09
  • 3
    Late to the party I know, but I found this [article](http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/systemd-house-of-horror/tomcat.html) really helpful. The author clearly knows his stuff regarding systemd. – Mark Gibson Mar 19 '16 at 11:50
  • 4
    I ended up using `catalalina.sh run` which will run in the current windows and still does all the setup needed for running the jar – oers Jan 25 '18 at 16:16
  • 4
    @MarkGibson: I think the article has moved, i found it [here](https://jdebp.eu/FGA/systemd-house-of-horror/tomcat.html) – huch Jun 12 '18 at 08:48
  • 1
    @huch it keeps moving. For anyone interested just search for "systemd house of horror tomcat". Quite an eye opener. – Willa Jun 02 '21 at 08:45
8

At this point, I'd use JSvc. But wrap it with a Systemd script if I had to.

  1. Keep in mind JSvc is just another executable. So a regular system user can configure a JSvc service for instance. It's safe to say that on most distros Systemd requires root privileges to be configured.

  2. I've also written Java programs that use JSvc and ProcRun.exe by wrapping a small Java interface. This allows me to use the same service code and even JUnit integration tests on Unix and Windows OSes. So I would argue JSvc and ProcRun.exe together facilitate cross-platform service code.

  3. JSvc has some interesting Java specific options that may be useful to you. Such as how to start the JVM ( process or DLL ), etc. You can write a lot of those into a Systemd script, but I suspect you'd just be rewriting JSvc in Bash at that point.

So maybe it's not very compelling for your specific Tomcat example. But there are some advantages to using the tiny JSvc service wrapper over Systemd.

kervin
  • 11,672
  • 5
  • 42
  • 59
0

You should use jsvc if you want to run tomcat with non-root privileges but using low port(<1024).

Also disabling shutdown port becomes available. It cannot be used when running Tomcat with the standard shell scripts though, as it will prevent shutdown.bat|.sh and catalina.bat|.sh from stopping it gracefully.

user3132194
  • 2,381
  • 23
  • 17
  • That's not entirely true you can allow a service to bind below port 1024 by proving the service with: ``` CapabilityBoundingSet=CAP_NET_BIND_SERVICE ``` – Thaodan Jun 09 '23 at 11:40