Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable scope in the shell level

Tags:

linux

bash

shell

Recently I have been reading The Advanced Bash Script and I find something about the variable scope between parent and children shells puzzle me so much. Here it is:

Scene: there are some ways to spawn a child shell: first, (command-lists); second, execute a non-built-in command or a script, and so on.

Since when we run a script in the parent script, the child script can not see the variables in the parent shell. Why is it possible that in the (command-lists) struct the child shell can seen the variable in the parent shell. e.g

  1. (command-lists)

    $ a=100
    $ (echo $a)
    100
    $
    
  2. run a script

    $ cat b.sh
    echo $a
    $ a=100
    $ ./b.sh
    # empty
    

How?

like image 283
Red Lv Avatar asked Feb 16 '23 11:02

Red Lv


1 Answers

In the case where you have a sub-shell run in the original script:

(command1; command2; ...)

the sub-shell is a direct copy of the original shell created by fork(), and therefore has direct access to its own copy of all the original variables available to it.

Suppose the commands (command1, command2 etc) in the sub-shell are themselves shell scripts. Those commands are executed by the sub-shell calling fork() and then exec() to create a new shell, and the new shell does not inherit the non-exported variables from the original shell.


Addressing your examples directly:

$ a=100
$ (echo $a)
100
$

Here, the sub-shell has its own copy of all the variables (specifically, a) that the parent shell had access to. Any changes made in the sub-shell will not be reflected in the parent shell, of course, so:

$ a=100
$ (echo $a; a=200; echo $a)
100
200
$ echo $a
100
$

Now your second example:

$ cat b.sh
echo $a
$ a=100
$ ./b.sh

$ . ./b.sh
100
$ source ./b.sh
100
$ a=200 ./b.sh
200
$ echo $a
100
$ export a
$ ./b.sh
100
$

The variable a is not exported, so the first time b.sh is run, it has no value for $a so it echoes an empty line. The second two examples are a 'cheat'; the shell reads the script b.sh as if it was part of the current shell (no fork()) so the variables are still accessible to b.sh, hence it echoes 100 each time. (Dot or . is the older mechanism for reading a script in the current shell; the Bourne shell in 7th Edition UNIX used it. The source command is borrowed from the C shells as an equivalent mechanism.)

The command a=200 ./b.sh exports a for the duration of the command, so b.sh sees and echoes the modified value 200 but the main shell has a unchanged. Then when a is exported, it is available to b.sh automatically, hence it sees and echoes the last 100.

like image 163
Jonathan Leffler Avatar answered Feb 26 '23 09:02

Jonathan Leffler