SubShell Level: 1
parent_var=Parent
Subshell is over.
Now ParentShell start again.
Shell Over: ParentShell Level: 0
sub_var is not defined in ParentShell
结论:
* 在shell中使用管道可以产生子shell。
* 由管道产生的子shell可以直接引用父shell定义的本地变量。
* 由管道产生的子shell中定义的变量不能被父shell引用。
* 由管道产生的子shell不能异步执行,只能在执行完毕后才能返回到父shell环境。(在shell中使用管道不可以实现其他程序的多线程并发功能。)
### 3.使用“()”功能
#! /bin/bash
parent_var=“Parent”
echo “Shell Start: ParentShell Level: $BASH_SUBSHELL”
( #<==使用小括号,将命令集括起来
echo “SubShell Level:
B
A
S
H
_
S
U
B
S
H
E
L
L
"
s
u
b
v
e
r
=
"
S
u
b
"
e
c
h
o
"
p
a
r
e
n
t
_
v
a
r
=
BASH\_SUBSHELL" sub_ver="Sub" echo "parent\_var=
BASH_SUBSHELL"subver="Sub"echo"parent_var=parent_var”
sleep 2
echo “Subshell is over.”
) #<==小括号结束
echo “Now ParentShell start again.”
echo “Shell Over: ParentShell Level:
B
A
S
H
_
S
U
B
S
H
E
L
L
"
i
f
[
−
z
"
BASH\_SUBSHELL" if [ -z "
BASH_SUBSHELL"if[−z"sub_var” ];then
echo “sub_var is not defined in ParentShell”
else
echo “sub_var is defined in ParentShell”
fi
Shell Start: ParentShell Level: 0
SubShell Level: 1
parent_var=Parent
Subshell is over.
Now ParentShell start again.
Shell Over: ParentShell Level: 0
sub_var is not defined in ParentShell
结论:
* 在shell中使用()可以产生子shell。
* 由()产生的子shell可以直接引用父shell定义的本地变量。
* 由()产生的子shell中定义的变量不能被父shell引用。
* 由()产生的子shell不能异步执行,只能在执行完毕后才能返回到父shell环境。(在shell中使用管道不可以实现其他程序的多线程并发功能。)
### 4.通过调用外部shell脚本产生子shell
父脚本
#! /bin/bash
parent_var=“Parent”
export parent_env_var=“Parent Env”
echo “Shell Start: ParentShell Level: $BASH_SUBSHELL”
sh ./20_1_4_SubShell.sh
sleep 1
echo “Now ParentShell start again.”
echo “Shell Over: ParentShell Level:
B
A
S
H
_
S
U
B
S
H
E
L
L
"
i
f
[
−
z
"
BASH\_SUBSHELL" if [ -z "
BASH_SUBSHELL"if[−z"sub_var” ];then
echo “sub_var is not definded in ParentShell”
else
echo “sub_var is defined in ParentShell”
fi
子脚本
#! /bin/bash
echo “SubShell Level:
B
A
S
H
_
S
U
B
S
H
E
L
L
"
s
u
b
v
a
r
=
"
S
u
b
"
e
c
h
o
"
s
u
b
_
v
a
r
=
BASH\_SUBSHELL" sub_var="Sub" echo "sub\_var=
BASH_SUBSHELL"subvar="Sub"echo"sub_var=sub_var”
echo “parent_var=
p
a
r
e
n
t
_
v
a
r
"
e
c
h
o
"
p
a
r
e
n
t
_
e
n
v
_
v
a
r
=
parent\_var" echo "parent\_env\_var=
parent_var"echo"parent_env_var=parent_env_var”
sleep 2
echo “SubShell is over.”
执行结果
Shell Start: ParentShell Level: 0
SubShell Level: 0
sub_var=Sub
parent_var= #<==子shell无法引用父shell变量,因此等号后面为空
parent_env_var=Parent Env #<==子shell可以引用父shell定义的全局环境变量
SubShell is over.
Now ParentShell start again.
Shell Over: ParentShell Level: 0
sub_var is not definded in ParentShell
结论:
* 调用外部shell脚本产生的子shell可以直接引用父shell定义的环境变量
* 调用外部shell脚本产生的子shell中定义的变量(或者环境变量)不能被父shell引用
* 调用外部shell脚本产生的子shell不能异步执行,只有执行完毕后才能返回到父shell环境
## shell调用脚本的模式说明
在主脚本中嵌套脚本的方式有很多,常见的为fork、exec、source三种模式,这三种调用脚本的方式有一定的区别。
### fork模式调用脚本知识
fork模式是最普通的脚本调用方式,及直接在父脚本里面用“/bin/bash /directory/script.sh”来调用脚本,或者在命令行中给script.sh脚本文件设置执行权限,然后使用/directory/script.sh来调用脚本。
使用上述方式调用脚本的时候,系统会开启一个SubShell(子shell)执行调用的脚本,SubShell执行的时候ParentShell还在,SubShell执行完毕后返回到ParentShell。最后的结论是SubShell可以从ParentShell继承环境变量,但是默认情况下SubShell中的环境变量不能带回ParentShell。
执行方式说明:
`/directory/script.sh` #<== 对脚本赋予执行权限,直接执行脚本。
`/bin/bash /directory/script.sh` #<== 在不赋予执行权限时,利用执行解释器执行
### exec模式调用脚本
exec模式与fork模式调用脚本的方式不同,不需要新开一个SubShell来执行被调用的脚本。被调用的脚本与父脚本在同一个shell内执行,但是使用exec调用一个新脚本以后,父脚本中的exec执行之后的脚本内容就不会再执行了,这就是exec和source的区别。
执行方式说明:
`exec /directory/script.sh`
### source模式调用脚本
source模式与fork模式的区别是不会新开一个SubShell来执行被调用的脚本,而是在同一个shell中执行,所以在被调用的脚本中声名的变量和环境变量都可以在主(父)脚本中获取和使用。
source模式与exec模式相比,最大的不同之处是使用source调用一个新脚本以后,父脚本中source命令行之后的内容在自脚本执行完毕后依然会被执行。
执行方式说明:
`source /directory/script.sh` #<== 使用source不容易被误解,而“.”和“./”相近,容易被误解。
`. /directory/script.sh` #<== “.”和source命令的功能是等价的。
### 对比fork模式与source模式的区别
对于fork模式,有以下结论:
* 父脚本执行后的PID信息与嵌套脚本(子shell脚本)执行后的PID信息不同,说明fork模式调用脚本确实产生了子shell
* 父脚本的变量信息会被嵌套如的脚本(子shell)引用,“[SubShell.sh]( ) get$ParentVar=Parent”中等号右边的Parent即为调用父脚本变量后输出的结果。
* 在嵌入的脚本(子shell)中定义的变量信息无法被父脚本引用,“[ParentShell.sh]( ) : Get : $SUB\_VAR=”中等号右边内容为空,表示没有引用到父脚本的变量。
对于source模式,有以下结论:
* 父脚本执行后的PID信息与嵌套脚本(子shell脚本)执行后的PID信息一致,说明source模式调用脚本不会产生子shell,而是在同一个shell里执行,此项与fork模式不同。
* 在嵌入的脚本(子shell)中定义的变量信息可以被父脚本引用,“[ParentShell.sh]( ) : Get: $SUB\_VAR=Sub”中等号右边内容为Sub,表示引用了子shell脚本中的变量,此项与fork模式不同。
### 对比exec模式与source模式的区别
对于exec模式,有以下结论:
* 父脚本执行后的PID信息与嵌套脚本(子shell脚本)执行后的PID信息一致,说明exec模式调用脚本同不会产生子shell,而是在同一个shell里执行,此项与source模式相同
* 父脚本的变量信息会被嵌入的脚本(子shell脚本)引用,“[SubShell.sh]( ) get$ParentVar=Parent”中等号右边的Parent即为调用父脚本变量后输出的结果,此项与fork及source模式都相同。
* 利用exec模式执行嵌入脚本(子shell脚本)的问题是,在执行完嵌入脚本后,紧接着嵌入脚本后的所有父脚本命令将不再执行,而是直接退出父脚本,此项与fork及source模式都不同。
## shell调用脚本3种不同模式的应用场景
1. fork模式调用脚本的应用场景
fork模式调用脚本主要应用于常规嵌套脚本执行的场合,嵌套的脚本只是执行相应的命令操作,不会生成相应的进程信息,父脚本不需要引用嵌套的脚本内的变量及函数等信息,其次在嵌套脚本中定义的变量及函数等不会影响到父脚本中相同的信息定义。
2. exec模式调用脚本的应用场景
exec模式调用脚本需要应用于嵌套脚本在主脚本的末尾执行的场合,因此,此种模式的应用并不多见,并且可以被source模式完全取代。
3. source模式调用脚本的应用场景
source模式调用脚本是比较重要且最常用的一种嵌套方式,主要应用之一是执行嵌套脚本启动某些服务程序。例如:在利用嵌套脚本启动Tomcat程序并生成PID程序文件时,如果选择fork模式,那么生成的PID文件信息就和执行“ps -ef”命令输出的PID信息不一致,这将会导致执行kill `cat tomcat\_pid` 命令时,不能正确关闭Tomcat程序,而选择source模式就可以解决此问题。
source模式调用脚本的另外一个应用就是使得嵌套脚本中的变量及函数等信息被父脚本使用,从而实现更多的业务处理。
![](https://img-blog.csdnimg.cn/img_convert/9a8cb5f8c0ec69e6499adead0da6e95b.png)
最全的Linux教程,Linux从入门到精通
======================
1. **linux从入门到精通(第2版)**
2. **Linux系统移植**
3. **Linux驱动开发入门与实战**
4. **LINUX 系统移植 第2版**
5. **Linux开源网络全栈详解 从DPDK到OpenFlow**
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/59742364bb1338737fe2d315a9e2ec54.png)
第一份《Linux从入门到精通》466页
====================
内容简介
====
本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/9d4aefb6a92edea27b825e59aa1f2c54.png)
**本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。**
> 需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**