Scope of an exported variable in shell
Solution 1
Global variables live from the moment they're set up until the moment they're unset or the process ends. Global (nor local) variables are not inherited by unrelated child processes (if the child process is a fork (a subshell) then it gets a copy of everything -- exported or nonexported).
Global exported variables are like global variables, but they're also automatically inherited (as part of the process environment) by, even unrelated, child processes. (With exports, you can pass a variable such as CXXFLAGS
to a process such as make
, which most definitely isn't a subshell of your shell, and every process that that make
spawns will also get that variable too.)
In your example ()
creates a subshell, which gets a copy of everything.
The foo
command modifies the subshell by adding an exported variable and then the subshell ends without ever utilizing the exported variable (no grandchild inheritted it). Now, no information implicitly travels from child processes to parent processes. What children do in their environment has no affect on their parents. That is the reason why your variable one
is unset.
BTW, those eval
s are an unnecessary eval
in this context.
Solution 2
Enclosing a command between ( )
will result in command being in a sub shell.
This can be usefull if one is to pipe, or exit.
( date ; cmd1 ; cmd2 ) | grep ...
will result of concatenate the first 3 command and giving output to grep
(in this case).
You might consider {}
, as well as reading man page for bash
(list) list is executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT
below). Variable assignments and builtin commands that affect the
shell's environment do not remain in effect after the command completes.
The return status is the exit status of list.
{ list; }
list is simply executed in the current shell environment. list must be
terminated with a newline or semicolon. This is known as a group
command. The return status is the exit status of list.
Note that unlike the metacharacters ( and ), { and } are reserved
words and must occur where a reseved word is permitted to be recognized.
Since they do not cause a word break, they must be separated
from list by whitespace or another shell metacharacter.
Related videos on Youtube
Bhagyesh Dudhediya
Updated on September 18, 2022Comments
-
Bhagyesh Dudhediya almost 2 years
Say I have a script where I have exported a variable as seen below:
#!/bin/bash foo(){ eval export one=1 } foo1(){ eval export two=2 } (foo) foo1 echo "one=$one" echo "two=$two"
However I got the following output:
root@centos1:~>/tmp/test.sh one= two=2
What might be reason that I am unable to see value of
$one
and can see$two
? -
schily about 8 years
$one
is not empty but unset. There is a difference between both states. -
PSkocik about 8 years@shily thx. fixed