The printenv command lists a number of environment variables most of which I have not defined. From where does it read these values? Where are the environment variables stored in Linux? strace printenv gave an indication to me that it opens /usr/lib/locale/locale-archive but I did not get a clear idea.
They are not defined in one single place. When your shell starts it usually reads a bunch of initializing scripts that set some environment variables, like for example
/etc/profile and for example in the case of Bash also
~/.bashrc. But this depends mostly on your distribution and your shell.
On top of this, a lot of applications that you are probably running, like for example X11 or your terminal emulator will set more variables in your environment.
So, as you see, these variables come from many different places. With
strace you could see where they are read from if they were being set at the execution time of
printenv, but that's not the case, because they are set earlier and kept in memory.
I don't know of any good way to trace back where a variable that has been set has come from. But for example if you use Bash you could start it with the
--verbose parameter to at least see which files it's reading on start up. Like
Processes inherit environment variables from their parent, they don't read them from a file. Most programs have the same environment variables as the program that started them and never modify them.
When you log in, a number of environment variables are set by the login system. The details depend on the distribution and specific system configuration. You can expect to find
PATH everywhere, and
SHELL are very common.
On most systems, environment variables can also be listed in
~/.pam_environment; these files are read when you log in by any method. When you log in to an interactive shell (in text mode or over SSH), or often but not always when you log in in graphical mode (it depends on the display manager,
the session manager and the distribution), the shell reads
~/.profile (or possibly other files depending on the shell and the setup). These files, as well as other files and programs involved in the login process, often define environment variables.
There's no miracle recipe to find out which program or configuration causes an environment variable to be set. You can look for definitions in your configuration files and the system configuration files:
grep -rs SOMEVAR /etc ~/.[!.]*
This won't find environment variable names that are hard-coded in applications. You can also look at different processes to see which ones have it, which gives an indication of which one set it. On Linux, the following command shows the environment variables of process 1234:
tr \\0 \\n </proc/1234/environ | sort
Note that shells have their own variables which are not environment variables. An assignment in a shell script or on the command line (
VAR=VALUE) sets a shell variable; if the variable is exported (
export VAR=VALUE or
export VAR after
VAR has a value), it becomes an environment variables that is visible by child processes. All environment variables automatically become shell variables.