父 shell,子 shell ,export 与 变量传递
来源:互联网 发布:上海ug编程培训班 编辑:程序博客网 时间:2024/05/23 02:05
当我们在一个 shell 里运行一个脚本程序时,该 shell 就会 fork 出一个新进程,从而启动了另一个命令解释器(由脚本中第一行的 #!/bin/xxx 指定,如 bash shell)来解释运行我们这个脚本。也就是说,这个新进程是一个子 shell,而之前的 shell 是个父 shell 。
在我们所运行的脚本里,我们还可以启动新的子 shell 进程,这些子 shell 进程使脚本并行地运行着多个子任务。一般而言,在一个脚本里执行一个外部命令(普通的可执行文件)时,shell 会 fork 出一个子进程,然后再用 exec 来执行这个程序;但是,bash shell 的内置命令(builtin)却不会这样,它们是直接执行的。所以,等价的内置命令的执行速度会比执行外部命令要来的快。
在一对括号 (...) 里可以放置一组指令,这些指令是在一个子 shell 里执行的。在子 shell 里的变量不能被这段子 shell 外的代码直接访问,也就是说子 shell 里的变量不能被父 shell 所存取,实际上它们是局部变量。
这里可以参考:(( ))和 [[ ]] 和 shell 与 命令的执行 这两篇文章。
下面用一段代码进行测试:
运行输出:
在上面的代码中,BASH_SUBSHELL 是一个环境变量,它表示进入子 shell 的层级,比如处于当前 shell 时,该变量值为 0;当在当前 shell 派生的子 shell 里时,该变量值为 1;如果该子 shell 又派生出一个子 shell,那么该变量在此间的值就为 3,以此类推。
在代码中,( ) 里的代码段是在子 shell 里执行的,而 inner_variable 作为局部变量,它的值可以在 ( ) 这段代码里 echo 出来,但是一旦返回到父shell 时,它就是未定义的,所以会输出“ inner_variable undefined in main body of shell”。也就是说,局部变量不能被外部代码所访问。
从输出可以看到,在子 shell 中和父 shell 中变量 outer_variable 的输出值是一样的;相对应的 outer_variable2 变量即使在子 shell 中进行了修改,但是当返回到父 shell 对其输出时,它却还是父 shell 中原来所赋的值。从这里可以看出,子 shell 可以 “感知” 父 shell 中的变量,但它不能修改它。其本质的原因和 fork() 函数的原理有关。在 UNIX/LINUX 中,fork 出来的子进程实际上是对父进程的一种拷贝,而子 shell 就是父shell fork 出来的一个子进程,所以它理所当然的有了父shell 中的一片拷贝。所以,子 shell 里的 outer_variable 和 outer_variable2 变量虽然和父 shell 的同名,但它们并不是同一个变量,而是父 shell 里的一个副本。
说到父shell 和 子 shell,那么会想到 export 这个命令。export 也是 bash 的一个内置命令。它主要是用来将父 shell 里的变量导出供子 shell 使用。它有如下特征:
1. 用 export 导出的变量放在“导出变量列表”中,它可以被子 shell (子 shell 的子 shell 也是如此)拷贝并使用。
2. 被 export 出来的变量虽然可以被子 shell 使用,但它也只是一个拷贝,而不会影响到父 shell 中的值以及其它子 shell 中的值。
看下面示例;
1. 先在当前 shell 里 export 一个变量:
2. 运行一个脚本 echo 此变量(该脚本只有一句话即 echo $exp8temp ):
由上可见,父 shell 里 export 的变量可以被子 shell 读取。
3. 测试一下子 shell 更改此变量是否会影响父 shell 里的值,子 shell 代码如下:
检验上面的情景:
可见子 shell 对父 shell 里 export 出来的变量进行修改并不能影响到父 shell。这说明了,子 shell 只是在“导出变量列表“里对该变量进行了一个拷贝。但反过来,父shell再次更改此变量时,子 shell 再去读时,读到的是新值,而不是原来的值。
4. 如果在子 shell 里 export 出的变量,父 shell 是否能读到呢?
先将下面一段代码放在后台运行:
然后在在 30 秒内在父 shell 里读取一下 $exp9temp 的值,发现输出为空。所以我们得出结论,export 出来的变量不能导出到父进程或者是父进程的环境里。一个自己称可以继承父进程的东西,而不能反过来去影响父进程。
那么子 shell 有什么办法可以向父 shell 传递自己的变量吗?下面方法可以考虑:
1. 通过一个中间文件进行:
运行输出:
2. 通过命令替换:
运行输出:
执行命令替换符(两个反单引号)之间的命令也是在子 shell 来完成的。
3. 使用命名管道:
运行输出:
关于有名管道创建命令 mkfifo 可参考:http://www.groad.net/bbs/read.php?tid-3707.html
4. 使用 here 文档:
运行输出:
在我们所运行的脚本里,我们还可以启动新的子 shell 进程,这些子 shell 进程使脚本并行地运行着多个子任务。一般而言,在一个脚本里执行一个外部命令(普通的可执行文件)时,shell 会 fork 出一个子进程,然后再用 exec 来执行这个程序;但是,bash shell 的内置命令(builtin)却不会这样,它们是直接执行的。所以,等价的内置命令的执行速度会比执行外部命令要来的快。
在一对括号 (...) 里可以放置一组指令,这些指令是在一个子 shell 里执行的。在子 shell 里的变量不能被这段子 shell 外的代码直接访问,也就是说子 shell 里的变量不能被父 shell 所存取,实际上它们是局部变量。
这里可以参考:(( ))和 [[ ]] 和 shell 与 命令的执行 这两篇文章。
下面用一段代码进行测试:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash
echo
"Subshell level = $BASH_SUBSHELL"
outer_variable=Outer
outer_variable2=Outer2
(
echo
"Subshell level INSIDE subshell = $BASH_SUBSHELL"
inner_variable=Inner
outer_variable2=Outer_var_changein_subshell
echo
"From Subshell,\"inner_variable\"=$inner_variable"
echo
"From parent shell,\"outer\"=$outer_variable"
echo
"From parent shell, \"outer\"=$outer_variable2"
)
echo
"In parent shell, check \"outer_variable\" value:$outer_variable"
echo
"In parent shell, check \"outer_variable2\" value:$outer_variable2"
echo
echo
"Subshell level OUTSIDE subshell = $BASH_SUBSHELL"
echo
if
[ -z
"$inner_variable"
]
then
echo
"inner_variable undefined in main body of shell"
else
echo
"From main body of shell,\"inner_variable\"=$inner_variable"
fi
exit
0
运行输出:
引用beyes@debian:~/shell$ ./subshell.sh
Subshell level = 0
Subshell level INSIDE subshell = 1
From Subshell,"inner_variable"=Inner
From parent shell,"outer"=Outer
From parent shell, "outer"=Outer_var_changein_subshell
In parent shell, check "outer_variable" value:Outer
In parent shell, check "outer_variable2" value:Outer2
Subshell level OUTSIDE subshell = 0
inner_variable undefined in main body of shell
在上面的代码中,BASH_SUBSHELL 是一个环境变量,它表示进入子 shell 的层级,比如处于当前 shell 时,该变量值为 0;当在当前 shell 派生的子 shell 里时,该变量值为 1;如果该子 shell 又派生出一个子 shell,那么该变量在此间的值就为 3,以此类推。
在代码中,( ) 里的代码段是在子 shell 里执行的,而 inner_variable 作为局部变量,它的值可以在 ( ) 这段代码里 echo 出来,但是一旦返回到父shell 时,它就是未定义的,所以会输出“ inner_variable undefined in main body of shell”。也就是说,局部变量不能被外部代码所访问。
从输出可以看到,在子 shell 中和父 shell 中变量 outer_variable 的输出值是一样的;相对应的 outer_variable2 变量即使在子 shell 中进行了修改,但是当返回到父 shell 对其输出时,它却还是父 shell 中原来所赋的值。从这里可以看出,子 shell 可以 “感知” 父 shell 中的变量,但它不能修改它。其本质的原因和 fork() 函数的原理有关。在 UNIX/LINUX 中,fork 出来的子进程实际上是对父进程的一种拷贝,而子 shell 就是父shell fork 出来的一个子进程,所以它理所当然的有了父shell 中的一片拷贝。所以,子 shell 里的 outer_variable 和 outer_variable2 变量虽然和父 shell 的同名,但它们并不是同一个变量,而是父 shell 里的一个副本。
说到父shell 和 子 shell,那么会想到 export 这个命令。export 也是 bash 的一个内置命令。它主要是用来将父 shell 里的变量导出供子 shell 使用。它有如下特征:
1. 用 export 导出的变量放在“导出变量列表”中,它可以被子 shell (子 shell 的子 shell 也是如此)拷贝并使用。
2. 被 export 出来的变量虽然可以被子 shell 使用,但它也只是一个拷贝,而不会影响到父 shell 中的值以及其它子 shell 中的值。
看下面示例;
1. 先在当前 shell 里 export 一个变量:
引用beyes@debian:~/shell$ export exp8temp="hello world"
beyes@debian:~/shell$ echo $exp8temp
hello world
2. 运行一个脚本 echo 此变量(该脚本只有一句话即 echo $exp8temp ):
引用$ ./exp8.sh
hello world
由上可见,父 shell 里 export 的变量可以被子 shell 读取。
3. 测试一下子 shell 更改此变量是否会影响父 shell 里的值,子 shell 代码如下:
1
2
3
4
5
#!/bin/bash
exp8temp=
"hello shell"
echo
$exp8temp
检验上面的情景:
引用beyes@debian:~/shell$ ./exp8.sh
hello shell
beyes@debian:~/shell$ echo $exp8temp
hello world
可见子 shell 对父 shell 里 export 出来的变量进行修改并不能影响到父 shell。这说明了,子 shell 只是在“导出变量列表“里对该变量进行了一个拷贝。但反过来,父shell再次更改此变量时,子 shell 再去读时,读到的是新值,而不是原来的值。
4. 如果在子 shell 里 export 出的变量,父 shell 是否能读到呢?
先将下面一段代码放在后台运行:
1
2
3
4
5
6
7
#!/bin/bash
export
exp9temp=
"hello world"
sleep
30
exit
0
然后在在 30 秒内在父 shell 里读取一下 $exp9temp 的值,发现输出为空。所以我们得出结论,export 出来的变量不能导出到父进程或者是父进程的环境里。一个自己称可以继承父进程的东西,而不能反过来去影响父进程。
那么子 shell 有什么办法可以向父 shell 传递自己的变量吗?下面方法可以考虑:
1. 通过一个中间文件进行:
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
(
subvar=
"hello shell"
echo
"$subvar"
> temp.txt
)
read
pvar < temp.txt
echo
$pvar
运行输出:
引用$ sh subandp.sh
hello shell
2. 通过命令替换:
引用#!/bin/bash
pvar=`subvar="hello shell";echo $subvar`
echo $pvar
运行输出:
引用$ ./subandp.sh
hello shell
执行命令替换符(两个反单引号)之间的命令也是在子 shell 来完成的。
3. 使用命名管道:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
mkfifo
-m 777 npipe
(
subsend=
"hello world"
echo
"$subsend"
> npipe &
)
read
pread < npipe
echo
"$pread"
exit
0
运行输出:
引用beyes@debian:~/shell$ ./var.sh
hello world
关于有名管道创建命令 mkfifo 可参考:http://www.groad.net/bbs/read.php?tid-3707.html
4. 使用 here 文档:
1
2
3
4
5
6
7
8
#!/bin/bash
read
pvar << HERE
`subvar=
"hello shell"
echo
$subvar`
HERE
echo
$pvar
运行输出:
引用$ ./subandp.sh
hello shell
方法应该还有很多,这些方法的本质原理基于进程间的通信。
原文链接:http://www.groad.net/bbs/read.php?tid-3708.html
0 0
- 父 shell,子 shell ,export 与 变量传递
- 父 shell,子 shell ,export 与 变量传递
- 父 shell,子 shell ,export 与 变量传递
- 父 shell,子 shell ,export 与 变量传递
- shell 中export变量导出到子进程
- 父Shell与子Shell
- 父Shell与子Shell
- shell与export命令
- shell与export命令
- shell 与 export命令
- shell 与 export命令
- shell 与 export命令
- shell 与 export命令
- shell 与 export命令
- shell与export命令
- shell与export命令
- shell与export命令
- export命令与shell
- vmware虚拟机复制后网卡设置
- CentOS6.5配置IP地址的三种方法
- cookie与session比较
- 第三篇:VS2012中,调用opencv库,在程序中定义了变量,编译没有问题,运行时会报错“变量使用没有定义”
- HDU 2013 蟠桃记
- 父 shell,子 shell ,export 与 变量传递
- qml:1807: Error: Insufficient arguments
- 系统技术架构图
- 读书笔记--如何阅读一本书
- R语言基础
- c++实现多态的原理
- CSS基础
- Android源码之高仿爱奇艺
- 《高质量程序设计指南C/C++语言》笔记总结