Suppose before starting a service you have to set an environment variable containing the current date and time. Furthermore this environment variable should only be propagated to the service you are just going to start.
While using a Linux distribution featuring a SysV-style init system this was a no-brainer of course. After all, services were started using plain shell scripts. So all you had to do was to make use of e.g. command substitution:
# pseudo code of a SysV-style init system shell script <...> EXPORT_NAME=output-$(TZ=UTC date +%%Y%%m%%d) <now go on and just start the desired service>
Most current Linux distribtions use systemd
nowadays. Under systemd services are not started
imperatively using shell scripts but rather
declaratively using configuration files.
The command to execute when starting a service with
systemctl start export
is specified using the
ExecStart option. The important thing
here to remember is that the given command is not executed in
a shell context. Therefore you can not use the command substitution
feature of the shell here. So this will not work:
# file /etc/systemd/system/export.service [Unit] Description=Export Service After=syslog.target [Service] Type=oneshot User=exporter WorkingDirectory=/tmp/ # THIS WON'T WORK ExecStart=EXPORT_NAME=output-$(TZ=UTC date +%%Y%%m%%d) /appl/export
And this will not work either:
# file /etc/systemd/system/export.service [Unit] Description=Export Service After=syslog.target [Service] Type=oneshot User=exporter WorkingDirectory=/tmp/ # THIS WON'T WORK EITHER Environment=output-$(TZ=UTC date +%%Y%%m%%d) ExecStart=/appl/export
So how to get this to work? Here is a possible solution:
# file /etc/systemd/system/export.service [Unit] Description=Export Service After=syslog.target [Service] Type=oneshot User=exporter WorkingDirectory=/tmp/ ExecStart=/bin/bash -c 'EXPORT_NAME=output-$(TZ=UTC date +%%Y%%m%%d-%%H%%M%%S) exec /appl/export'
Here we tell systemd to execute the
bash command. The
bash will then set the
EXPORT_NAME environmental variable making use of command substitution. After this the
bash will execute the
exec command. Finally
exec replaces the
bash with the given command.
exec is a
builtin command of the Bourne Shell.
By the way. You have to escape the
% character by prefixing it with another
Otherwise systemd would interpret e.g. the
%m would be replaced with
the hostname of the running system at the point in time the unit configuration is loaded.
Many settings in the service unit configuration file resolve so called
Those specifiers may be used to write generic unit files referring to runtime or unit parameters
that are replaced when the unit files are loaded. More information about
this can be found here.
A note about Netcup
Netcup offers inexpensive, yet powerfull web hosting packages, KVM-based root servers or dedicated servers for example. Using a code generated by my Netcup coupon code generator you can even save more money (5$ on your first purchase, 30% off any KVM-based root server, ...).