4

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?

7

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 evals are an unnecessary eval in this context.

|improve this answer|||||
  • 1
    $one is not empty but unset. There is a difference between both states. – schily May 11 '16 at 11:32
  • @shily thx. fixed – PSkocik May 11 '16 at 11:34
1

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.
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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