From my understanding exec command replaces the calling shell program with the command without forking a child process. Also if I understand correctly exported variables are the ones that are passed to its spawned children. But since the spawning doesn't happen when you exec command, why does the command still inherits its variables from the calling shell?

To illustrate the case (run in Bash) here is an example:

$ cat vartest1
export y
exec ./vartest2

$ cat vartest2
echo x = $x
echo y = $y

$ ./vartest1
x =
y = 1

Why does vartest2 inherits the exported variables from vartest1 but not the local ones, if vartest2 is not a child process of vartest1 when run with exec?

  • 1
    The fork family of system calls have nothing to do with environment variables. It's in the exec family of system calls where environment variables are set. So instead of (paraphrasing) fork(); exec(something, args, env), you just have exec(something, args, env) when running exec something.
    – muru
    Mar 26 at 5:07
  • I don't know much the C lang. But does it come from your answer that the default behavior of the exec command that it passes environment variables of the calling shell to the command run, but doesn't do so for the local ones? Mar 26 at 5:33

1 Answer 1


Unix doesn't use spawn, it uses fork. Fork clones a process (with a very short list of differences in the child), typically immediately before an exec. (As said in comment..) The exec system call is where environment variables are passed to the new process. It is up to the parent to either default to using its own env for the new executable or passing something else that is possibly completely different.

In bash (and possibly other shells), the -c option to the exec command can clear the environment. It is also possible to change environment variables the usual way by putting variable=valuebefore exec on the command line. If none of these things are done, the new executable inherits what the shell had.

Note that while fork() makes very few changes in the child, exec() makes a large number of changes. For example, signal handlers are reset. Open file handles can be marked as close on exec so the new executable doesn't get them. The memory map is redone from scratch. And things like environment variables can be inherited or replaced as a set.

So your assumptions about what fork and exec do are somewhat reversed from actual use. The philosophy here is that fork() is frequently done to create a new process whose memory is about to all be thrown away to a new executable, so there's no point in doing any work to change it or set it up. After the fork, the running program may at its option continue with the same memory (typically set as copy on write, opportunistically cloning memory pages as needed), or using exec() to replace it completely with a new program, disassociating from the parent's shared memory pages with no changes to them. Environment variables are one of the few things that can potentially (but not certainly) survive after exec() is called.

You must log in to answer this question.

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