Question
Given a systemctl
template and unit file as follows, I am trying to obtain the environment variables that will ultimately be passed to a process on start (regardless of whether the service is currently running):
/etc/systemd/system/example-template@.service
...
[Service]
Environment="VAR1=val1"
Environment="VAR2=val2"
...
/etc/systemd/system/example-template@example-unit.service.d/unit.conf
[Service]
Environment="VAR2=Overridden by %i"
After exploring the options offered by systemctl
I haven't been able to find anything other than systemctl show example-template@example-unit --property=Environment
, the output of which contains the variables as a single string:
Environment=VAR1=val1 VAR2=Overridden by example-unit
However as it contains no convenient delimiter I would prefer to avoid having to parse this to recover the original variables.
Originally I had thought to utilise the EnvironmentFile
directive by moving the variables into their own files and sourcing them from my script. Unfortunately at least one of my variables requires the %i
parameter expansion which is not performed on those defined in an EnvironmentFile
.
Is there a better way to achieve what I need?
Context
We have 80 Tomcat instances which have been migrated from an OpenSUSE server to a CentOS 7 server. Historically these have been managed via a System V init script which was cloned for each instance. The init scripts are functionally identical, but differ by the values they export before delegating start/stop commands to the catalina.sh
script shipped with Tomcat. Updating any common functionality requires applying the change to all 80 files.
In addition to this we have a wrapper script which delegates to catalina.sh
, adding such options deleting deployed files or tailing log files. This is the script which requires knowledge of the environment variables; currently these are exposed by invoking the init script with particular arguments, whether the server is running or not.
Instead of sticking with System V and consolidating the common functionality into a single sourceable script (my original intention), I decided to migrate to systemd
to take advantage of its support for unit file templates as they seemed designed with this scenario in mind. This would allow me to globally define our default Tomcat settings while allowing individual instances to override certain variables (e.g. to increase JVM memory or test an applciation against a new version of Tomcat). The environment variables unique to each instance include such things as the PID file (which catalina.sh
needs to be made aware of) and Tomcat base (config) location.
With that in mind the issue I'm facing is that the aforementioned wrapper script would no longer have access to the environment variables for a Tomcat instance (for example one of the variables is the CATALINA_HOME
path which contains the deployed applications, logs, and config files for the server). Some of the functions of the script do not require the server to be running (such as cleaning a stopped server), so obtaining the environment from the process is not viable.
Now I could make the wrapper script derive (guess) this information from the unit name, or forego running the Tomcat servers as a service entirely by making the wrapper script invoke the catalina.sh
script directly; however I was hoping to have the sole source of information about the service be the service itself, and also be able to utilise some of the features of systemd
such as automatically restarting the service if it enters a failed state.
Version Info
- CentOS Linux release 7.6.1810
- systemd 219
- bash 4.2.46(2)-release
tr '\0' '\n' </proc/<PID>/environ
.journalctl -u foo@instance
. I imagine similar better ways could exist for the rest of your wrapper script's functionality.