I have read that a forked child process gets its environment (such as env variables) inherited from the parent process. It is also said that local shell variables are not available to the forked child processes, but if that is the case how can a local variable defined in a shell be echoed by its child process (echo in this case)? as echo is the child process of the shell.
About linux : Shell-local-variable-in-forked-process-linux-closed
I have read that a forked child process gets its environment (such as env variables) inherited from the parent process.
Not “such as”. In that sense of the word “environment”, the environment consists of environment variable names and values only. There as a larger, more inclusive execution context for each process, but its “environment” is just a set of variables.
It is also said that local shell variables are not available to the forked child processes
You clarified in comments on the question that by “local shell variables” you mean variables that are not marked for export. Yes, by definition, these are not provided to child processes.
if that is the case how can a local variable defined in a shell be echoed by its child process (echo in this case)? as echo is the child process of the shell.
It can’t and doesn’t, because
echo doesn’t do that. By which I mean, it does nothing with any environment variables inherited from its parent process.
I guess you must be asking about something like this:
# not exported: foo=something echo "$foo"
, which will print “something” followed by a newline. But that does not rely on variable
foo being exported to the process in which
echo runs. Rather, the shell expands the variable reference as part of a larger collection of expansions that it performs on each command before executing it. The child process receives a literal
something as its argument.
To further elucidate, try this:
foo=something bash -c "echo $foo" bash -c 'echo $foo'
The output is one “something” and one blank line. Why? Because the parent shell expands the variable reference inside double quotes, but not the one in single quotes. In neither case does the child
bash process receive variable
foo in its environment, but in the first case it does not need it, because by the time that process receives it, the command string it is asked to execute has no reference to
$foo. The same is not true in the second case.
Child processes get a copy of their parents’ environment. They can see all the
exported environment variables and even modify them, but those modifications won’t be seen by the parent.
Variable set in parent visible in child:
$ export foo=bar $ echo "parent: $foo" parent: bar $ (echo "child: $foo") child: bar
Modification in child not visible in parent:
$ (foo=baz; echo "child: $foo") child: baz $ echo "parent: $foo" parent: bar
If you don’t
export a variable then it is only a shell variable and not part of the environment. In that case you can see the variable in a subshell since subshells are special cased:
$ foo=bar $ (echo "child: $foo") child: bar
However if you create a child process via any other mechanism, such as by explicitly invoking
bash, it won’t be visible since it’s not part of the environment and doesn’t survive the fork:
$ foo=bar $ bash -c 'echo "child: $foo"' child: