Pass an environment variable from current shell to a systemd unit
I am trying to pass an environment variable defined in the current shell to one of the systemd
unit I am writing.
DB_URL=databus.dev.mysite.io:8080
I am using this in a python script which is running as a service. My systemd
unit will run this script as a unit making use of the variable for its working.
[Unit]
Description=device-CompStatus: Computes device availability status
[Service]
Type=simple
ExecStart=/usr/bin/bash -c "/usr/bin/python /opt/deviceCompStatus/deviceCompStatusHandler.py"
Restart=always
[Install]
WantedBy=default.target
The way am using the variable in Python script would be
if os.environ.get('DB_URL') is not None:
dbEndPoint = "http://" + os.environ['DB_URL']
The problem is am not able to use the variable when running the script in systemd
. I looked up couple of resources Using environment variables in systemd units, it says to use assignment under [Service]
directly as
[Service]
Environment=DB_URL=databus.dev.mysite.io:8080
As you can see, my DB_URL
could change depending upon the environment I am deploying my machine, it could be a developer, or a production setup, in which the URLs would vary.
How do I do this dynamically? i.e. pass whatever value available to DB_URL
to systemd
environment?
I also tried using the EnvironmentFile=
option to define a file and pass it to service. But the same problem again, my variable could be dynamic and cannot be hardcoded.
Update
After using the option
systemctl import-environment DB_URL
I am able to see the variable available in the environment of systemd
which I confirmed by
systemctl show-environment
DB_URL=databus.dev.mysite.io:8080
LANG=en_US.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
but still the value is not reflected in the python
application which I run. Is os.environ('DB_URL')
a wrong way to access the variable?
You can affect the global systemd environment for all future commands (until reboot) by using
sudo systemctl set-environment var=value
or if you already have var
exported in your environment, you can use
sudo systemctl import-environment var
After starting your unit you can remove the variable with unset-environment
similarly.
As this is global in effect you would be better off simply writing the line DB_URL=databus.dev.mysite.io:8080
into some file /some/file
and setting EnvironmentFile=/some/file
in your unit.
An alternative method is to use a template unit myunit@.service
which is started with systemctl start myunit@'databus.dev.mysite.io:8080'
. You can then recover this parameter as %i
inside the unit, for example in the [Service]
section with a line like:
Environment=DB_URL=%i
For what it’s worth, 50-systemd-user.sh from systemd itself provides a way to import environment variables DISPLAY and XAUTHORITY which you can refer:
#!/bin/sh
systemctl --user import-environment DISPLAY XAUTHORITY
if command -v dbus-update-activation-environment >/dev/null 2>&1; then
dbus-update-activation-environment DISPLAY XAUTHORITY
fi
https://github.com/systemd/systemd/blob/master/xorg/50-systemd-user.sh
In case if you have environment variables set in your current terminal and just have it exported to the systemctl
with sudo
, you can use,
sudo -E systemctl import-environment <LIST OF ENVIRONMENTS TO BE AVAILABLE FOR SERVICE>