Search code examples
hsqldbsystemdinit

Run HSQLDB as a systemd service using the sample init script


The HSQLDB docs have instructions for running HSQLDB as a daemon on Unix with a sample init script. However, this assumes a System V setup, while I am targeting a systemd-based setup.

A challenge with HSQLDB is that the shutdown procedure is tricky—it involves connecting to the database and issuing a shutdown command, thus you pretty much need a script even with systemd.

While systemd comes with compatibility features for SysV init scripts, which automatically create a systemd wraper around each init script, I have tried to implement a native systemd service, relying on the init script as far as possible (since, as established before, the complex shutdown logic requires a script).

My approach has been to place the init script in /usr/sbin and create the following systemd service wrapper around it:

[Unit]
Description=HSQLDB Server
After=network.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/hsqldb.pid
User=hsqldb
WorkingDirectory=~
ExecStart=/usr/sbin/hsqldb start
ExecStop=/usr/sbin/hsqldb stopcompact

[Install]
WantedBy=multi-user.target

However, this fails because the init script expects to be root in various places. The script itself has a check which causes it to fail when run as a user that doesn’t have write access to the root of the file system—this is a check which can be removed from the script, but then creating the pid file in /run fails.

Apart from relying on compatibility features, what is an easy way to make this work? Would it work to have systemd run the script as root (by setting User in the service file)? Are there any reasons against doing so? In that case, what other options do I have?


Solution

  • This works with a few modifications:

    • In the .service file, drop the User= setting: this will cause systemd to run the init script as root.
    • In the same file, drop WorkingDirectory= as it would just control the directory in which the init script runs (which can run from anywhere).
    • The init script runs from the home dir of the DB service account, hence this will be the default path for a number of files (e.g. server.properties and any files referenced from there)—make sure they are in the right place.
    • Systemd expects the service process to be owned by the account which launched it (root in this case) OR the PID file to be owned by root. The HSQLDB init script doesn’t do that by default—be sure to insert chown root $PIDFILE just before the call to exit 0 (line 455 in my case).

    With these changes, HSQLDB starts and stops cleanly. The only issue is that I get a warning from systemd that says:

    Supervising process 1541 which is not our child. We'll most likely not notice when it exits.
    

    Which probably means systemd won’t notice if the service crashes or otherwise exits without being stopped by systemd.