How to ask systemd service to reload its environment variables on runtime
Solution 1
The environment is copied into the process' address space when the process is created. Changes in the environment only affect newly started processes, you can't change the environment of a running program from the outside.
You'll need some kind of interprocess communication (IPC) mechanism for what you are trying to achieve, or just simply write a new value into a file and have your program poll the contents of the file.
Solution 2
Unless you are willing to restart the service under consideration (i.e. terminate the running process and launch a new one), this won't work. Environment variables are an individual attribute of a process, they are inherited from the parent upon startup (i.e. when the parent process fork
s). There is no way to alter environment variables of running processes (not regarding hacks like directly manipulating the process' memory via /proc/pid/mem
). Thus, even waking the process up by SIGUSR1
and having it reread its configuration (as many services and daemons are implemented to do) won't help - the process would find the very same environment variables as before.
For the behavior you ask for I suggest you consider to get configuration parameters from a file.
Related videos on Youtube
ferranrigual
Updated on September 18, 2022Comments
-
ferranrigual over 1 year
Question
My C++ application runs as a systemd service. I need to configure it using environment variables, and be able to reload the value of the variables during runtime without restarting the application.
I created a .conf file and used the Environment directive in it, and I execute daemon-reload after changing the value in the .conf file. But the service does not notice the change.
I know about the systemctl reload command, but I don't know what to set in the ExecReload directive.
C++ application code
#include <unistd.h> #include <fstream> using namespace std; int main(int argc, char** argv) { while (true) { char * cp = getenv("BAR"); string s = ""; if (cp) s = (string) cp; fstream fs; fs.open("/tmp/foo", ios_base::app); fs << s << endl; fs.close(); sleep(1); } return 0; }
Service description
Path: /etc/systemd/system/foo.service
[Unit] Description=Testing configuration reloading [Service] ExecStart=/home/user/foo_application Type=simple [Install] WantedBy=default.target
Service configuration file
Path: /etc/systemd/system/foo.service.d/foo.conf
[Service] Environment="BAR=2"
My previous (re)search
https://serverfault.com/a/590732/379539
https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html
https://www.freedesktop.org/software/systemd/man/systemctl.html
-
ferranrigual over 7 yearsThanks for your answer. Both yours and the previous one are valid answers. I accepted the previous one because it was posted first. But upvoted both of them (will be effective once I have 15 reputation on this site).