How to ask systemd service to reload its environment variables on runtime

5,074

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 forks). 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.

Share:
5,074

Related videos on Youtube

ferranrigual
Author by

ferranrigual

Updated on September 18, 2022

Comments

  • ferranrigual
    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
    ferranrigual over 7 years
    Thanks 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).