I am trying to setup a brand new installation of Ubuntu 22.10. I need to make some environment variables globally available. I have read in the Man pages that the correct way to do this is to provide a file in the /etc/environment.d directory with a name like 90-myfile.conf. When I try this, the environment variables are not established. If, instead, I put the variable definition into /etc/environment it is picked up. Is there something additional that I need to do? Using a command processor such as bash is not on because the variables need to be globally available.
-
"global" is very slippery. Exactly what context do you need these variables to be set? – user10489 Mar 12 '23 at 18:57
-
Every possible context that can make use of environment variables. – Jonathan Mar 12 '23 at 18:59
-
I don't think there is a single "global" context. There are multiple global contexts, and each gets environment variables from a different source. You need to be specific. Or at least make a list. Some contexts even reset environment variables to remove "global" ones. – user10489 Mar 12 '23 at 19:03
-
My understandinfg has been the the environment variables defined in /etc/environment and in environment.d are the global conttext that gives a starting point for every other environment. As for systemd, I find varying comments about its use of environment.d, but little that seems authoritative, I also find comments stating that all user provided environment variables should be placed in environment.d – Jonathan Mar 12 '23 at 19:08
-
Nearly every one of those statements is wrong. – user10489 Mar 12 '23 at 19:25
-
It turned out to be a permission problem with the files going into environment.d Group and Other needed read access. – Jonathan Mar 12 '23 at 19:43
-
@Jonathan - could you add this as an answer and then mark it as the correct one? Makes it much easier to find. – azernik Jul 25 '23 at 08:10
1 Answers
In unix, the environment is passed from a parent process to a child process. The parent process has complete control of the child's initial environment. By default, the child inherits the parent's environment, but the parent can pass something completely different, and the child can change it afterwards. As such, there is no "global" environment. There is an "initial" environment, but no global environment.
So, if nothing is explicitly set, the environment is inherited from whatever parent process last set it before forking.
Every operating system (and every distro) handles setting the initial environment differently. Since this is asking about Ubuntu, I'll limit things to that.
In Ubuntu, systemd starts the first processes, and has control of that initial environment. Systemd chooses to not have a way to set a global default environment within itself, but it has provisions for setting variables in different contexts.
- systemd-environment-d-generator sets initial environment for user manager instances.
- systemd.environment-generator has separate config files for each manager service
- pam_env.conf modifies the environment for users that log in (see man pages for environ(7) and pam_env.conf)
- For bash and sh,
/etc/environmentcan set variables when the shell starts; these can be inherited by subprocesses. Most shell instances read this, but some don't, and they can be explicitly told not to. - Each shell can read
/etc/profileor/etc/bash.bashrcwhich in turn may read files from/etc/profile.d, but again, not every shell instance does this, and the shell can be told to not read these or only read these. - Each user's shell init files can modify the environment.
- Programs like
sshandsudohave whitelists and blacklists of variables that are intentionally inherited or intentionally removed for subprocesses. - Services like systemd and cron typically inherit and pass a very minimal set of environment variables. Cron allows setting variables in each config file that are "global" for that config file.
- The
envcommand can modify the environment of a command before it is started.
This list is not exhaustive, there are probably more sources. And none of these are "global" -- environment variables are explicitly local to each process, although they can be inherited from a global source.
- 5,583
-
I was using "global" in the same way that you are using "initial" to describe an initial set of environment variables. If the ones that I set are not presented, then I will have to look at the requirements of that specific environment. But putting environment variables into environment_d will ensure that user supplied variables are supplied to most processes that run in login shells. – Jonathan Mar 12 '23 at 20:18
-
Yes, that's why I included the sources for the initial environment. That's about as close as you get to "global". – user10489 Mar 12 '23 at 20:21