systemd, EnvironmentFile, re-using variables – how?

I am migrating from upstart to systemd. I am having a bit of trouble making the transition with the EnvironmentFile directive. I cannot get this EnvironmentFile to work:

########################################################
# Catalina Settings
CLUSTER_BASE=/d01/tomcat/prod/xyz
CATALINA_BASE=$CLUSTER_BASE/1
CATALINA_TMPDIR=$CATALINA_BASE/temp
CATALINA_HOME=/usr/share/tomcat7
CATALINA_PID=/run/tomcat/tc-prod-xyz-1.pid

########################################################
# Java Settings
JAVA_HOME=/usr/lib/jvm/default-java/jre
JAVA_OPTS=-Djava.awt.headless=true
JAVA_OPTS=$JAVA_OPTS -server
JAVA_OPTS=$JAVA_OPTS -Xms2048m
JAVA_OPTS=$JAVA_OPTS -Xmx2048m
JAVA_OPTS=$JAVA_OPTS -XX:MaxPermSize=2048m
JAVA_OPTS=$JAVA_OPTS -XX:+UseParallelGC
JAVA_OPTS=$JAVA_OPTS -XX:+AggressiveHeap
JAVA_OPTS=$JAVA_OPTS -javaagent:$CLUSTER_BASE/newrelic/newrelic.jar

It would appear that this type of statement where I re-use a variable:

JAVA_OPTS=$JAVA_OPTS -XX:+UseParallelGC

is not supported in systemd like it was in upstart. Does systemd support something like this or do I need to make one long hard to read statement?

Asked By: Van

||

Do I need to make one long hard to read statement?

No

A line ending with a backslash will be concatenated with the following one, allowing multiline variable definitions.

Answered By: sourcejedi

You could use bash to expand your variables.

Environment file:

BLA=bla
BLABLA=${BLA}${BLA}

Use bash -c to execute the command:

ExecStart=/usr/bin/bash -c 'echo ${BLA} .. ${BLABLA}'

Output:

bash[4771]: bla .. blabla
Answered By: ctx

Unfortunately that file you have is actually a shell script. In the past, most init systems/scripts have interpreted files which provide environment variables by using the shell, so you could get away with doing shell things in them. Systemd however does not do this. The environment file is truly an environment file, not a script. This is documented in the systemd.exec man page:

Variable expansion is not performed inside the strings, however, specifier expansion is possible. The $ character has no special meaning.

Therefore you have 2 options.

  1. Expand out all your variables manually. Meaning use CATALINA_BASE=/d01/tomcat/prod/xyz/1.

  2. Evaluate the file with the shell:
    ExecStart=/bin/bash -ac '. /path/to/env_file; exec /path/to/program'

Answered By: phemmer

In the specific case of Tomcat (as in this question), I found that it is easier to put most of these settings in bin/setenv.sh, which is executed by Tomcat at startup, and evaluates the variables in the shell script as expected.

So in /etc/systemd/system/tomcat.service I only specify the Environment variables for CATALINA_BASE and CATALINA_HOME, and then I put the rest of the stuff in ${CATALINA_BASE}/bin/setenv.sh.

Answered By: isapir

Another option: Have a secondary unit that runs before this one and creates an EnvironmentFile it can use: https://stackoverflow.com/a/42841480/32453

The secondary unit can use bash for instance. Seems to be the systemd way for importing env. 😐

Answered By: rogerdpack
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.