http://roclinux.cn/?p=1277 

為了防止某些網站的惡性轉載,特在每篇文章前加入此資訊,還望讀者體諒。

===

[正文開始]

如果你對子Shell的概念不甚瞭解,如果你對export的用法還沒吃透,如果你不知道Shell如何管理你的變數,請閱讀本文。否則,請複習本文。^_^

情景一:建立一個shell指令碼var1.sh,其內容為:

[rocrocket@rocrocket SHELL]$ cat -n var1.sh
1    #!/bin/bash
2    echo :$myvar:

然後在終端上執行變數賦值語句並用echo顯示此變數:

[rocrocket@rocrocket SHELL]$ myvar=hello
[rocrocket@rocrocket SHELL]$ echo $myvar
hello

但是當執行var1.sh指令碼,想顯示myvar變數時,情況卻並非你所願:

[rocrocket@rocrocket SHELL]$ bash ./var1.sh
::

顯然,var1.sh並沒有看到使用者在終端中定義的myvar變數。可見,在終端中設定的變數,在執行的shell指令碼中是無法看到的。

情景二:我們建立一個指令碼var2.sh,內容為:

[rocrocket@rocrocket SHELL]$ cat -n var2.sh
     1	#!/bin/bash
     2	myvar=50
     3	echo :$myvar:

此時,使用者在終端設定myvar的值並顯示此值,然後再執行var2.sh,看看結果吧:

[rocrocket@rocrocket SHELL]$ myvar=100
[rocrocket@rocrocket SHELL]$ echo $myvar
100
[rocrocket@rocrocket SHELL]$ bash var2.sh
:50:

可見,終端中設定的值,在shell指令碼中是無法改變的;而且,終端也無法改變shell腳本里面設定的變數的值。

階段總結:

在Shell工作機制中,存在一個子shell的概念,上面的兩個情景展現的就是子shell的形象。子shell是登入shell為了執行某個指令碼程式而建立的一個全新的shell,這個全新的shell只會使用自己的區域性變數,對父shell(登入shell)的區域性變數不屑一顧。而且,子shell和父shell對對方的區域性變數都不會有任何冒犯,井水不犯河水。

引子:

有些事情偏偏是需要子shell和父shell有所互動的,這就需要有一個變數是子shell和父shell都能看到和修改的。這時候,export出現了,它可以“匯出變數”。

情景三:建立一個新的shell指令碼var3.sh,其內容如下:

[rocrocket@rocrocket SHELL]$ cat -n var3.sh
     1	#!/bin/bash
     2	echo mylocal=$mylocal
     3	echo myglobal=$myglobal

在var3.sh指令碼中,設定了兩個變數,一個是mylocal,表示區域性變數,一個是myglobal,表示全域性變數。
在終端上給此兩個變數賦值,然後執行指令碼程式var3.sh,很明顯,結果如你所願,是空值:

[rocrocket@rocrocket SHELL]$ mylocal=1
[rocrocket@rocrocket SHELL]$ myglobal=2
[rocrocket@rocrocket SHELL]$ bash var3.sh
mylocal=
myglobal=

我們針對myglobal執行export來匯出變數,再看看結果:

[rocrocket@rocrocket SHELL]$ export myglobal
[rocrocket@rocrocket SHELL]$ bash var3.sh
mylocal=
myglobal=2

看,我們的指令碼程式已經看到了myglobal的值了,看來export將myglobal匯出,真是起到作用了。

階段總結:

他的內幕是這樣的:當使用export來匯出一個變數時,當前shell就會將此變數放到“匯出變數列表”中,一旦在某個時刻需要建立子shell時,就會將這個匯出變數列表拷貝一份給子shell,這樣子shell也就有所應當的看到了這些被匯出的變量了。

(為了能讓10歲以前小朋友看懂,更形象的說:從前有個母親叫shell,shell她手裡攥著“匯出變數列表”和“區域性變數列表”兩件寶貝,當shell生育了小孩(名叫子shell)的時候,她就把“匯出變數列表”這件寶貝複製一份,交給她的孩子,而shell手裡的另一件寶貝“區域性變數列表”則不會交給小孩)

引子:

現在子shell如果想改變這份“匯出變數列表”中的某些內容,那麼父shell到底能不能察覺呢?父shell會不會隨著子shell一起修改這些值呢?

情景四:看看整個過程:

[rocrocket@rocrocket SHELL]$ export myglobal=10
[rocrocket@rocrocket SHELL]$ cat -n var4.sh
     1	#!/bin/bash
     2	myglobal=33
     3	echo myglobal=$myglobal
[rocrocket@rocrocket SHELL]$ bash var4.sh
myglobal=33
[rocrocket@rocrocket SHELL]$ echo $myglobal
10

可見,在子shell是無法改變父shell中的“匯出變數列表”中變數的值的。子shell只能修改自己手裡的那份“匯出變數列表”中變數的值。

階段總結:

子shell是無法改變父shell中的“匯出變數列表”中變數的值的。
變數一旦被匯出,對所有後續執行的子shell,該變數都是匯出變數。

關於export -p:

可以執行export -p來檢視當前shell的匯出變數列表。這其中一定是包括了從父shell繼承來的匯出變數列表。

全文總結:

1 沒有匯出的變數是區域性變數,子shell是看不到的。
2 匯出變數列表被複制給子shell,子shell可以修改和存取它,但是這種修改父shell看不到。
3 匯出變數列表的上述特性對於直接產生的子shell生效,對於由子shell產生的後繼子shell也是如此。
4 export可以在變數賦值之後用,也可以在變數賦值之前用。

over~