What I'm trying to understand is where does a child process inherit exported variables from it's parent process

What I'm trying to understand is where a child process inherits exported environment variables from? I understand the exec() system call overwrites environment variable created by the fork()... But how does exec() cause exported environment variables to be included with a newly created child process if all the environment variables are overwritten? My best guess is that exported environment variables are somehow excluded from being overwritten... But I can't confirm this

EDIT I edited my question to be clearer with what I am asking


2 Answers 2


There are no global environment variables. They are passed from parent to child.

  • fork does not change the environment variables.
  • exec without the e post-fix does not change the environment variables.
  • exec with e post-fix overrides environment variables.

As well as using the e post-fixed execs to change the environment, you can also do:

int pid = fork() //new process with same environment variables
if (pid == 0) {
    putenv   //add some environment variables
    unsetenv //remove some environment variables
    exec     //replace program. non e version of exec.
} …
int execve(const char *filename, char *const argv[],
           char *const envp[]);

-- man execve

The envp parameter provides all the environment variables of the executed program. If you pass no values in envp, the executed program will see no environment variables at all.

When you read an environment variable (getenv()), you always read it from the current process.

There is no way to set a system-wide environment variable. You can only configure the environment of your initial processes, setting variables to be passed on to child processes.

So it is possible to start another program with a completely different environment. But the most widely useful and common convention, is to start programs with a copy of your own environment. You might modify specific environment variables if you need to.

One exception is su --login and sudo --login ..., which cleanly reset the environment. Omitting the --login option to these commands allows some environment variables to be passed through... this sometimes causes "unexpected results".

  • When I said "global environment variables" I meant exported variables. If Bash has exported variables & a user starts a program. How & when does a child process acquire the exported variables from the parent process? You seemed to confirm how I thought this was happening when you said "start programs with a copy of your own environment". So does the exec() overwrite the region of memory the fork() created... But the child process inherits exported variables because they are NOT overwritten... Can you confirm if my understanding is accurate or not? Thanks!
    – Bodisha
    Dec 19, 2018 at 16:53
  • @Bodisha look at the execve() system call again. The argv parameter specifies the arguments to pass to the new program, as a list of strings (char *const ... []). The envp parameter specifies the environment variables, as a list of strings. So you can see environment working very similarly to arguments. (The strings should be formatted as NAME=value). If you also want to know a specific implementation detail, you should ask a specific question, specifying exactly which implementation you are asking about :-P. And mention why you want to know.
    – sourcejedi
    Dec 19, 2018 at 18:06
  • @Bodisha the set of exported shell variables (as shown by export -p) is the set of environment variables. Non-exported shell variables are not environment variables. This Wikipedia section is good: en.wikipedia.org/wiki/Environment_variables#Unix
    – sourcejedi
    Dec 19, 2018 at 21:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.