主题 : [转载]从学习export命令理解到的Shell环境和变量生存期 复制链接 | 浏览器收藏 | 打印
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
贡献值: 71 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
楼主  发表于: 2009-12-29 09:47

 [转载]从学习export命令理解到的Shell环境和变量生存期

管理提醒: 本帖被 kasim 执行加亮操作(2009-12-29)
原文由dragonbody发表于http://linux.chinaunix.net/bbs/viewthread.php?tid=322149

                
[原创] 从学习export命令理解到的Shell环境和变量生存期

http://www.chinaunix.net 作者:dragonbody  发表于:2004-08-12 08:49:46
发表评论】【查看原文】【Linux讨论区】【[url=javascript:window.close()]关闭[/url]】    
    

我自己也是一个菜鸟,接触linux没有多久,最近在学习BASH的export命令时碰到了一个难道(书上说export是将自定义变量变成系统环境变量):我在一个脚本文件中定义一个了变量,然后export变量,按照我自己的想法,执行完这个脚本后,在提示符下一定可以用echo显示出它的值,可结果却不是这样,脚本执行完后用set根本看不到有这个变量存在。为什么呢?我百思不得其解,最后将问题贴出来,一位前辈告诉我说用source+脚本文件就可以了,我试了一下果然可以,但一个新的问题又出来了。我将脚本中export命令删除后,用source一样可以。那这个export好像没有什么用呀。
    在经过多次尝试后发现了一些东西,是我自己猜的,如果有什么不对的地方,请指正,谢谢。
    执行一个脚本时,会先开启一个子shell环境(不知道执行其它程序是不是这样),然后将父shell中的所有系统环境变量复制过来,这个脚本中的语句就在子shell中执行。(也就是说父shell的环境变量在子shell中可以调用,但反过来就不行,如果在子shell中定义了环境变量,只对该shell或者它的子shell有效,当该子shell结束时,也可以理解为脚本执行完时,变量消失。)为了证明这一点,请看脚本内容:
test='value'
export test
这样的脚本执行完后,test实际上是不存在的。接着看下面的:
test='value'
export test
bash
这里在脚本最后一行再开一个子shell,该shell应该是脚本文件所在shell的子shell,这个脚本执行完后,是可以看到test这个变量的,因为现在是处于它的子shell中,当用exit退出子shell后,test变量消失。
    如果用source对脚本进行执行时,如果不加export,就不会在子shell中看到这个变量,因为它还不是一个系统环境变量呀,如脚本内容是:
test='value'
用source执行后,在shell下是能看到这个变量,但再执行bash开一个子shell时,test是不会被复制到子shell中的,因为执行脚本文件其实也是在一个子shell中运行,所以我再建另一个脚本文件执行时,是不会输入任何东西的,内容如:echo $test。所以这点特别注意了,明明在提示符下可以用echo $test输出变量值,为什么把它放进脚本文件就不行了呢?
    所以得出的结论是:1、执行脚本时是在一个子shell环境运行的,脚本执行完后该子shell自动退出;2、一个shell中的系统环境变量才会被复制到子shell中(用export定义的变量);3、一个shell中的系统环境变量只对该shell或者它的子shell有效,该shell结束时变量消失(并不能返回到父shell中)。3、不用export定义的变量只对该shell有效,对子shell也是无效的。
    后来根据版主的提示,整理了一下贴子:为什么一个脚本直接执行和用source执行不一行呢?这也是我自己碰到的一个问题。manual原文是这样的:Read and execute commands from filename in the current shell environment and return the exit status of the last command executed from filename.明白了为什么不一样了吧?直接执行一个脚本文件是在一个子shell中运行的,而source则是在当前shell环境中运行的。根据前面的内容,你也已经明白其中的道理了吧。
    困扰了我几天的问题终于可以圆满的解决了。



 sakulagi 回复于:2004-05-11 12:49:03

http://bbs.chinaunix.net/forum/viewtopic.php?t=321207
可以参考一下这个。
如果一定要撤销一个已经export了的变量,那么有两种方法:
unset VAR_NAME
export VARNAME=
后一种就是在“=”后边什么都不写。


 sakulagi 回复于:2004-05-11 12:51:21

感谢你写了这么长的文章,自己研究出来的东西印象深刻,有成就感;共享出来也是一件乐事,虽然不一定是很高深莫测的技术,可是一样值得鼓励。希望你再看一下source命令的说明,整理一下这个帖子,使之更完整。


 sakulagi 回复于:2004-05-11 12:57:10

至于source的行为为什么和直接执行一个script不一样:

bash的manual里提到,使用source script_name的时候,实际上并没有产生一个新的子shell来执行这个脚本,而是直接在当前的shell里执行的这个脚本。这样所有对环境变量的操作(就是export variable=value这样的操作),自然就是影响了当前的shell,所以用echo $variable可以看到这个环境变量已经被设置了。


 cgweb 回复于:2004-05-11 13:13:21

sakulagi点评的有理,希望楼主再接再厉,多出精华。


 dragonbody 回复于:2004-05-11 13:22:05

多谢各位前辈的指点,还希望能在以后的时间里给我更多的支持与鼓励。谢谢!


 dragonbody 回复于:2004-05-11 13:30:16

我原来也看过manual,原文是这样的:
Read and execute commands from filename in the current shell 
environment and return the exit status of the last command executed from filename.
可我当时并不能理解“当前shell环境”是一个什么样的概念,现在终于明白了。


 sakulagi 回复于:2004-05-11 13:34:33

试验方法,作一个不会马上退出shell脚本,比如里面只写一个cat命令。然后试试用和不用source两种情况,用pstree可以很容易看清楚是不是有子shell产生。


 網中人 回复于:2004-05-11 16:09:14

這個問題,或可參考一下 shell 十三問之 6:
http://bbs.chinaunix.net/forum/viewtopic.php?p=1583329#1583329


 sakulagi 回复于:2004-05-11 16:33:49

网老大的东东就比较深入系统了,呵呵。


 天外闲云 回复于:2004-05-11 20:11:32

引用:原帖由 "sakulagi" 发表:
至于source的行为为什么和直接执行一个script不一样:

bash的manual里提到,使用source script_name的时候,实际上并没有产生一个新的子shell来执行这个脚本,而是直接在当前的shell里执行的这个脚本。这样所有对..........


上次他问那个问题的时候我就这么说了(讲了半天父子shell和export功能),结果他只看你的没看我的,又跑出来问了!

大概是我自己没说明白吧。郁闷哪。


 sakulagi 回复于:2004-05-11 21:06:25

呵呵。只要最后都明白了就好。不管过程怎样,我相信我们每一个人其实都会对每一个帮助过自己的朋友心存感激的。


 lijun_2004 回复于:2004-06-20 13:12:51

新手上路,难免有挫折,我们在社区支持你, :em51:


 114 回复于:2004-08-12 08:49:46

当初我也遇到这个问题,困扰了我半天,呵呵,还好,我做了几次试验就想这答案,我还以为这是个简单的问题就没发出来了,还好,这位仁兄发出来了。




原文链接:http://linux.chinaunix.net/bbs/viewthread.php?tid=322149
转载请注明作者名及原文出处

"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."