`
caoruntao
  • 浏览: 480786 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

shell、子shell、变量和export

阅读更多

[转] http://roclinux.cn/?p=1277

情景一:建立一个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的值了,看来exportmyglobal导出,真是起到作用了。

阶段总结:

他的内幕是这样的:当使用export来导出一个变量时,当前shell就会将此变量放到导出变量列表中,一旦在某个时刻需要建立子shell时,就会将这个导出变量列表拷贝一份给子shell,这样子shell也就有所应当的看到了这些被导出的变量了。

(为了能让10岁以前小朋友看懂,更形象的说:从前有个母亲叫shellshell她手里攥着导出变量列表局部变量列表两件宝贝,当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
可以在变量赋值之后用,也可以在变量赋值之前用。

【转】http://doc.linuxpk.com/3862.html

 我自己也是一个菜鸟,接触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环境中运行的。根据前面的内容,你也已经明白其中的道理了吧。

  困扰了我几天的问题终于可以圆满的解决了。

 

分享到:
评论

相关推荐

    shell变量与创建子shell详解

    为了理解Shell变量和子Shell的创建,可以考虑一个实际的例子。例如,在父Shell中设置一个环境变量并创建一个子Shell,然后在子Shell中执行一个脚本。该脚本尝试访问父Shell中设置的环境变量。由于子Shell没有继承这...

    shell基础之环境变量 位置参数变量 预定义变量

    通过理解并熟练掌握这些Shell变量和概念,初学者能够更有效地编写和调试Shell脚本,提高自动化任务的效率。记得在实际应用中,适时地设置环境变量可以使脚本更具通用性,而位置参数变量则能帮助我们灵活处理用户输入...

    linux超级基础系列——shell变量(本地变量和环境变量).pdf

    Linux 超级基础系列 —— shell 变量(本地变量和环境变量) shell 变量是 Linux 系统中的一种重要概念,它允许用户存储和重复使用有用的信息,提高工作效率。shell 变量可以分为本地变量和环境变量两种。 什么是...

    从数据库中取变量传递给shell,生成环境变量

    从DB中取检索值传递给shell,生成环境变量 1. 编写myshellpara.sql 通过spool 执行一个SQL读取所要的值,结果保存在myshellvar_export.sh set feedback off; set heading off; set pagesize 0; set linesize 1000; ...

    shell 与 export命令

    实际上,`export`更准确的功能是将变量的值输出到子shell环境中,而不是简单地变为环境变量。这解释了为什么在使用`source`命令执行脚本时,即使没有使用`export`,仍然能在当前shell中访问到脚本中定义的变量。这是...

    shell编程基础之变量

    了解并熟练掌握这些基本的Shell变量知识,对于编写高效、可靠的Shell脚本至关重要。通过结合条件语句、循环结构和其他Shell特性,你可以创建出功能强大的自动化工具,提高日常Linux系统管理的效率。在实际应用中,...

    linux超级基础系列-shell变量(本地变量和环境变量)

    ### Linux超级基础系列——Shell变量(本地变量与环境变量) #### 一、Shell与Shell变量简介 在Linux操作系统中,Shell是一种用户与操作系统交互的重要工具,它可以解释用户的命令,并将其传递给内核或其他应用...

    shell程序设计——变量

    总之,Shell程序设计中的变量是实现功能的核心工具,理解其工作原理和用法对于编写强大的Shell脚本至关重要。通过不断实践和学习,你可以充分利用Shell的灵活性和强大功能,提高Linux系统的管理效率。

    linux运维学习笔记:Shell变量.pdf

    通过上述内容,我们了解到Linux Shell变量在日常运维中的重要性,以及如何在脚本中正确使用和管理变量,以提高脚本的可读性和可维护性。掌握这些知识对于成为一名合格的Linux运维工程师至关重要。

    Shell基础Bash变量环境变量PPT教案.pptx

    了解和熟练使用这些Shell变量对于日常的系统管理和自动化任务至关重要,因为它们允许我们定制Shell行为、存储和传递信息以及在不同的Shell上下文中保持状态。熟悉环境变量的设置和使用尤其重要,因为它可以方便地...

    Linux常用命令和管理07-shell之脚本编程变量和变量类型1

    变量分为不同类型,包括本地变量、环境变量(通过export导出)、局部变量和位置变量(如$1、$2等,其中$0表示脚本本身)。特殊变量如$?表示上一个命令的退出状态,$#表示传递给脚本的参数个数,$*或$@则用来引用所有...

    Tony老师聊shell—环境变量配置文件

    在Linux中,环境变量可以通过`export`命令来设置,并且可以在shell脚本中进行读取和修改。 #### 三、环境变量配置文件详解 1. **/etc/environment** - 这个文件包含了全局的环境变量设置。它被`login`程序读取并...

    工作笔记 shell 变量和运算符

    ### 工作笔记:Shell 变量和运算符 在 Linux 和 Unix 系统中,shell 脚本是一种强大的工具,它可以帮助我们自动化日常任务、处理系统管理和数据操作等。本文将详细介绍 shell 变量和运算符的相关知识点,帮助读者更...

    shell基础 之 数值运算与运算符 环境变量配置文件 shell登录信息

    本文将详细介绍shell基础中的数值运算与运算符、环境变量配置文件和shell登录信息。 一、shell中的数值运算符 在shell中,数值运算符用于对数字进行操作,常见的数值运算符有: * 加法:`a + b` * 减法:`a - b` ...

    Linux Shell脚本系列教程(三):变量和环境变量.docx

    Linux Shell 脚本系列教程(三):变量和环境变量 本文主要讲解了 Linux Shell 脚本系列教程(三):变量和环境变量,涵盖了普通变量、环境变量、获取字符串的长度等内容。 变量 在 Linux Shell 脚本中,变量是必...

    <Linux>shell 脚本环境变量问题深层探索【实践+实验】

    shell 脚本环境变量可以通过多种方式来设置和使用,例如使用 export 命令来设置环境变量,使用 ${变量名} 来获取环境变量的值等。 参数 ---------- 环境变量的参数可以是字符串、数字、数组等多种类型。环境变量...

    shell浅谈之九子shell与进程处理.docx

    每个Shell可以处理多个作业,这就涉及到了进程管理和子Shell的概念。 子Shell是Shell的一个关键特性,它是由父Shell通过调用fork函数创建的。在Shell中,命令分为内建命令和外部命令。内建命令直接由Shell执行,不...

    练习shell变量、重定向、管道等相关命令

    ### 练习Shell变量、重定向、管道等相关命令 在Linux和Unix系统中,Shell脚本是一种非常强大的工具,用于自动化任务处理、系统管理和数据处理等。熟练掌握Shell中的变量、重定向和管道操作对于提高工作效率至关重要...

    第二十一章:shell编程规范及变量1

    3. 变量作用域分为局部和全局,全局变量通过`export`使其在子进程中生效。 4. 引号的使用有讲究,`""`是弱引用,`''`是强引用,`$()`和``(反引号)用于命令替换,其中`$()`可嵌套。 5. 交互定义变量可通过`read -p`...

Global site tag (gtag.js) - Google Analytics