Question

I was wondering if there is a way to set an environment variable from a bash process and read it from another.

As environment variables' values are local to processes (besides the inheritance), one can't just do export FOO="bar" in a terminal and read it from another. I was then trying to get them through /proc/environ, but this is what I got:

etuardu@subranu:~$ FOO="foo" bash
etuardu@subranu:~$ strings /proc/$$/environ | grep FOO
FOO=foo
etuardu@subranu:~$ export FOO="bar"
etuardu@subranu:~$ strings /proc/$$/environ | grep FOO
FOO=foo
etuardu@subranu:~$ echo $FOO
bar

It seems I can just get the value that that environment variable had when the process started.
How about its current value?

Was it helpful?

Solution

This is not possible in general because of the way environment variables work.

When a process is first execed, the kernel supplies it with its initial set of environment variables together with some other stuff (mainly its argv vector, i.e. its command line). Thereafter, this list (like the argv vector) is just a regular C array of character pointers inside the process. The process is free to manage them however it likes, including completely recycling the memory that holds the strings for some other use if it wants to. It isn't safe for one process to go peeking inside any other process's memory space to find its environment variables.

Most types of processes do use the list of environment variables supplied by the kernel more or less as-is, perhaps querying it and modifying it with C library functions like getenv() and putenv(). If these processes run any other executables in their turn, they pass the same environment vector to the execve system call which they received at the start of their own execution, which means that the new executable gets the same environment (possibly enhanced by some calls to putenv()).

Shells are another matter. Because environment variables are so important in shell scripts, some shells use the environment vector supplied to them only as a "start value", and thereafter ignore it. They manage their environment variables using their own, more capable, data structures. When they execute child processes of their own, they pass a completely new environment vector to the new process, constructed from those internal data structures. This means that even if you were to peek into a shell's memory space to find its environment variables as suggested above, you would find only the initial set, not the environment that the shell is actually using!

What you might be able to do is query a process's initial set of environment variables, that is, the same vector that was passed to the executable when it started. But this is not portable, and there is considerable variation even among operating systems that support this. For example, in historical UNIXes, it is still a bit ugly because it still involves peeking into the process's memory space (albeit a special area of memory called the "user area"). Linux makes this possible more elegantly: the vector can be found as a text string in /proc/<pid>/environ. On most systems where it's possible to get this information, ps has an e option which is able to show it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top