[systemd-devel] Solution for evaluating variables in environment files

Frank Steiner fsteiner-mail1 at bio.ifi.lmu.de
Wed Oct 7 07:43:51 PDT 2015


Hi,

when switching from system-V to systemd one might run into the problem
that files specified with "EnvironmentFile=..." are not evaluated
(as they were before when e.g. /etc/init.d/apache2 executed
" . /etc/sysconfig.apache") but parsed by systemd itself.

Therefore stuff like
  [ -L "/usr/lib64/biojava" ] && export BIOJAVA=/usr/lib64/biojava || export BIOJAVA=/usr/lib/biojava
or
  bla="$blu"
or 
  bla="1"
  bla+=" 2"
or 
  bla="
  1
  2
  "

doesn't work in EnvironmentFiles (which is a real disadvantage of systemd,
by the way!). We have many files in /etc/sysconfig that do more than setting 
variables the simple way, e.g. we calculate the include-dirs for apache from 
the file system dynamically etc. Some solutions are posted over the net, we 
turned them into a little automated version of the 
'ExecStart=/bin/bash -c ". /etc/sysconfig/apache2; apache2 blabla'
solution that I'd like to share with those having similar problems. It avoids
creating specific drop-ins or changing the global service files when there
are a lot of services that you need to tweak.

We install two files, eg. /etc/sysconfig/container.start:
  #!/bin/bash
  service=${1%.service}

  [ -n "$service" ] || { echo "no parameter given to $0";  exit 1; }
  [ -r /usr/lib/systemd/system/${service}.service ] || { echo "/usr/lib/systemd/system/${service}.service not found by $0"; exit 1; }
  
  # variables set here must be exported (set -a) as the ExecStart command could be
  # another shell script that otherwise would not see these values
  set -a
  for name in `grep "^EnvironmentFile=" /usr/lib/systemd/system/${service}.service |sed 's/EnvironmentFile=//'`
  do
  . $name
  done
  set +a
  # works only with a single ExecStart line
  eval `grep "^ExecStart=" /usr/lib/systemd/system/${service}.service  |sed 's/ExecStart=//'`

and  /etc/sysconfig/container.conf:
 [Service]
  # notify like in apache2.service will not work this way
  Type=simple
  # avoid double execution of shell code in environment files
  EnvironmentFile=
  ExecStart=
  ExecStart=/etc/sysconfig/configuration.start %n

Thus, all you need to do now is creating a link 
/etc/systemd/system/apache2.service.d/container.conf -> /etc/sysconfig/container.conf
and then "systemctl start apache2" will evaluate all environment files before
starting apache.

This solution only works for service files with one ExecStart line where no
variables from the environment files are used in e.g. ExecStop (if that's
the case remove the "EnvironmentFile=" from container.conf).

Different versions of container.conf could be created for forking scripts
etc., but this simple version was enough for us to run e.g. apache2 and tomcat.

Maybe this helps someone else :-)
cu,
Frank

-- 
Dipl.-Inform. Frank Steiner   Web:  http://www.bio.ifi.lmu.de/~steiner/
Lehrstuhl f. Bioinformatik    Mail: http://www.bio.ifi.lmu.de/~steiner/m/
LMU, Amalienstr. 17           Phone: +49 89 2180-4049
80333 Muenchen, Germany       Fax:   +49 89 2180-99-4049
* Rekursion kann man erst verstehen, wenn man Rekursion verstanden hat. *


More information about the systemd-devel mailing list