14

I have a systemd service running under a specific user.

I erroneously assumed that the service would have access to the environment variables all users inherit from scripts/exports under /etc/profile.d

Is there a way to accomplish this without having to manually copy the variables in systemd unit file definition.

For example, I have the following

$ cat /etc/profile.d/somexports

export VAR1=VALUE1
export VAR2=VALUE2

Can this be passed / exported to a systemd service?

2 Answers 2

15

There are a few possible sources of environment:

  1. Using Environment= which lets you set variables
  2. Using EnvironmentFile= which lets you load values from a file
  3. Using PassEnvironment= which lets you define variables which should be passed from PID1.
  4. Static configuration (e.g. $USER)

It might sound like EnvironmentFile=/etc/profile.d/someexports is what you want, but that's not the case. /etc/profile.d/* is often sourced by your shell and can be parsed by your shell. systemd is shell agnostic and so it will not rely on bash syntax. The EnvironmentFile should contain new-line-separated variable assignments which is much stricter.

systemd's design discourages dynamically changing units or their environments. Even the EnvironmentFile= option was only added as a result of pressure and was later considered to be a mistake by systemd's developers. One example of this design is that $PATH does not affect which binaries are used. This keeps things more deterministic as when you define a unit, you are defining everything about how that unit should run without worrying about external influence.

So short answer is: No. you cannot load /etc/profile.d/* into systemd and that's intentional.

But the answer you probably want is: yes, you can load it. You just need to run your application through a shell.

You can do that by changing:

ExecStart=/usr/bin/myservice

To

ExecStart=/usr/bin/bash -lc myservice

That will cause bash to be the parent process, which loads /etc/profile.d/ and forwards that environment to its child. Also note that I did not specify a full absolute path to myservice. In this case, myservice will be based on $PATH and that may or may not be /usr/bin/myservice. You can see how this might make things more difficult to troubleshoot and that's the disadvantage of going this route.

6
  • 3
    Another reason why systemd does not care about /etc/profile or /etc/profile.d is that systemd is designed to be shell-agnostic. /etc/profile and the syntax used therein is specific to Bourne type shells. Systemd wants to be independent of shells, and it should be possible to use systemd on systems with different shells, and even on systems without any shell. Oct 31, 2021 at 15:42
  • Thank you for you answer. Assuming usage of ExecStart=/usr/bin/bash -c myservice will make bash to be the parent process, will it make any difference if -c was followed by the full executable name, e.g. as in ExecStart=/usr/bin/bash -c /usr/local/bin/myservice ?
    – pkaramol
    Oct 31, 2021 at 16:02
  • 1
    Nope, you can add the full executable name. I just removed it to describe some of the differences.
    – Stewart
    Nov 1, 2021 at 7:03
  • I finally found a solution to my problem: I wrote something like ExecStart=/usr/bin/bash -c 'source /etc/configfile && myservice' <rant> I miss somehow the simplicity of the scripts in /etc/init.d ; I'm working daily on a systemV based OS (Devuan), but I also have to work on systemd machines, and it can be painful. </rant>
    – Pierre
    Mar 27, 2023 at 17:38
  • How do you set/change variables for PID1?
    – BMWW
    Apr 7, 2023 at 6:27
5

I think this is addressed as follows

ExecStart=/bin/sh -lc /path/to/binary

The -l flag makes the shell invocation a login shell. We need this because only login shells source profile scripts.

$ bash --help | grep -- -l
GNU bash, version 4.4.12(1)-release-(x86_64-pc-linux-gnu)
    --login
2
  • 1
    What is the purpose of specifying a login shell here? Mar 23, 2022 at 18:38
  • 1
    with -l you can load the environment variables from user files , for example ~/.profile
    – juanpablo
    Mar 26, 2023 at 14:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .