子shell的概念
中文翻译过来的“子shell”叫法,实际上包括了“subshell”和“child shell”。
subshell是指: 对父shell的一个拷贝,共享了父shell的变量,函数,别名等,能用但修改只在subshell中生效。通过()
开启subshell。内置变量BASH_SUBSHELL
显示subshell的层数。
child shell是指: 重新开启的一个shell,不共享父shell的变量,函数,别名。一个纯新的环境。命令bash或者运行脚本就开启child shell。内置变量SHLVL
显示child shell的层数。
The Korn Shell: Unix & Linux Programming Manual :
A subshell is a separate copy of the parent shell, so variables, functions, and aliases from the parent shell are available to the subshell
# BASH_SUBSHELL
> echo $BASH_SUBSHELL
0
> (echo $BASH_SUBSHELL)
1 --进入1层 subshell
> ( ( ( ( (echo $BASH_SUBSHELL) ) ) ) )
5 --进入5层 subshell
> bash
> echo $SHLVL
1 --进入1层 child shell
> echo $BASH_SUBSHELL
0
> bash
> echo $SHLVL
2 --进入2层 child shell
> echo $BASH_SUBSHELL
0
一、进入子shell的方式
- 直接输入bash(退出 :exit,也无法继承和改变父shell中的普通变量,同脚本):child shell
()
中的命令是在子shell中实现:subshell- 运行脚本,脚本也是在子shell中实现 :child shell
二、差异
child shell是一个全新的环境,不共享父shell中的普通变量,普通变量只能通过export方式实现共享。
subshell 中的普通变量是可以从父shell中继承的,只是不能改变父shell中的变量值。
- 验证环境:
> cat /proc/version
Linux version 3.0.101-0.47.55-default (geeko@buildhost) (gcc version 4.3.4 [gcc-4_3-branch revision 152973] (SUSE Linux) ) #1 SMP Thu May 28 08:25:11 UTC 2015 (dc083ee)
()
的表现:
> x=10
> echo $x
10
> echo $$ #该命令用于显示当前shell进程号
10497 --父shell的进程号
> (echo $$;echo $x;ps;x=5;echo $x)
10497 -- 实际上还是父shell的进程
10 -- 进程中的x可取父进程中的x
5 -- 进程中的x被改变
PID TTY TIME CMD
3757 pts/0 00:00:00 bash #subshell进程进程号
3758 pts/0 00:00:00 ps
10497 pts/0 00:00:00 bash #父进程进程号
> echo $x
10 -- 父进程中的x没有改变
- bash命令
> bash #进入子shell
> echo $$
3609
> ps
PID TTY TIME CMD
3609 pts/0 00:00:00 bash --child shell进程
5359 pts/0 00:00:00 ps
10497 pts/0 00:00:00 bash
> echo $x
-- 空
> x=5;echo $x
5
> exit #退出子进程
> echo $$
10497 --回到父shell
> echo $x
10 -- 父shell中x没有改变
- 脚本中子shell的表现:
将echo $$;echo $x;ps;x=5;echo $x
写入test.sh中
> echo $x
10
> ./test.sh
8794 --子shell的进程号
-- 无法获取父shell中的变量值
PID TTY TIME CMD
8794 pts/0 00:00:00 sh -- child shell 进程
8795 pts/0 00:00:00 ps
10497 pts/0 00:00:00 bash
5 -- 子shell中定义的变量
> echo $x
10 --父shell中值不变
三、差异的原因
()
的子shell能获取父shell中变量值的原因因为是subshell,$()
一样能够获取到父shell中变量的值。$()
命令的()
表现和单独的()
一样,也是在子shell中运行,但能访问父shell变量,但不能改变父shell变量。
参考:
https://stackoverflow.com/questions/19462291/bash-subshell-parentheses-vs-dollar-parentheses
https://tldp.org/LDP/abs/html/subshells.html
https://www.cnblogs.com/ziyunfei/p/4803832.html