Search code examples
linuxenvironment-variablesredhatsystemd

How to get systemd variables to survive a reboot?


I have a product provided by a third party vendor. It includes many services for which they provide initd style startup scripts. There is one script for each service provided.

These scripts reference variables like JAVA_HOME, THE_PRODUCT_HOME and so on. The expectation from the vendor that I must edit these scripts manually and hard code the correct values. I would rather that these variables be initialised from environmental variables obtained from systemd when the system boots.

I know I can create an override configuration file for each of the services to provide the necessary envirables (a.k.a. environmental variables) using systemctl edit theService but:

  1. There are quite a few startup scripts
  2. The base variables are all the same
  3. I would like to avoid "systemctl edit"ing each of the supplied scripts if I can

So far I've tried using systemctl set-environment VAR_NAME=some_value.

This works perfectly - until I restart the system. It seems like the variables set this way are globally defined, but do not survive a reboot. I've also tried using systemctl daemon-reload just in case that is needed to "commit" the settings (but it doesn't seem to save the global envirables).

For now, I've edited each one of the supplied startup scripts and source /path/to/theGlobalVariablesINeed.sh

This works fine as a workaround but is not my preferred solution going forward...

Here is an illustration of what is happening:

define some variables

[root@dav1-td1 -> ~] # systemctl show-environment
LANG=en_US.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
[root@dav1-td1 -> ~] #

[root@dav1-td1 -> ~] # systemctl set-environment SYSD_PRODNAME_JAVA_HOME=/usr/java/jdk1.8.0_181-amd64/jre
[root@dav1-td1 -> ~] # systemctl set-environment SYSD_PRODNAME_HOME=/opt/TheProduct-1.2.3
[root@dav1-td1 -> ~] # systemctl daemon-reload        # This is optional, if I run the reload, or do not run the reload, the variables are still lost over a reboot.

demonstrate that the variables are set.

#### Now some variables are set, If I restart a service, the service will
#### Pick up these environmental variable settings.

[root@dav1-td1 -> ~] # systemctl show-environment
LANG=en_US.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
SYSD_PRODNAME_HOME=/opt/TheProduct-1.2.3
SYSD_PRODNAME_JAVA_HOME=/usr/java/jdk1.8.0_181-amd64/jre
[root@dav1-td1 -> ~] #

System restart

#### After restart, the variables have disappeared !?!?

[root@dav1-td1 -> ~] # systemctl show-environment
LANG=en_US.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
[root@dav1-td1 -> ~] #

As mentioned above, when I restart the system, any envirables I set using systemctl set-environment VAR=value are lost.

I need these variables to survive a restart (without using per service override files and without having to source a file that contains all of the variables)


Solution

  • There are different ways you can approach this problem.

    1. Set the environment variable using the systemd config

    You can edit the /lib/systemd/system/system.conf and add the content like below

    [Manager]
    DefaultEnvironment=A=B C=D
    

    2. Set the environment variable using another systemd service

    [Unit]
    Description=Example systemd service init
    
    [Service]
    Type=simple
    ExecStart=/bin/systemctl set-environment VAR_NAME=some_value
    
    [Install]
    WantedBy=sysinit.target
    

    The import point is using WantedBy=sysinit.target so this is loaded early

    and now we can create a simple service to test this

    [Unit]
    Description=Example systemd service.
    
    [Service]
    Type=simple
    ExecStart=/usr/bin/env
    
    [Install]
    WantedBy=multi-user.target
    

    and the result

    root@vagrant:/lib/systemd/system# systemctl status tarun
    ● tarun.service - Example systemd service.
       Loaded: loaded (/lib/systemd/system/tarun.service; enabled; vendor preset: enabled)
       Active: inactive (dead) since Sat 2019-06-15 11:31:17 UTC; 5s ago
      Process: 1712 ExecStart=/usr/bin/env (code=exited, status=0/SUCCESS)
     Main PID: 1712 (code=exited, status=0/SUCCESS)
    
    Jun 15 11:31:17 vagrant systemd[1]: Started Example systemd service..
    Jun 15 11:31:17 vagrant env[1712]: A=B
    Jun 15 11:31:17 vagrant env[1712]: C=D
    Jun 15 11:31:17 vagrant env[1712]: LANG=en_US.UTF-8
    Jun 15 11:31:17 vagrant env[1712]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    Jun 15 11:31:17 vagrant env[1712]: VAR_NAME=some_value