进入子shell的各种情况分析(2)

[root@linuxidc ~]# echo $BASHPID 65230 [root@linuxidc ~]# bash [root@linuxidc ~]# echo $BASHPID 65534

③.执行shell脚本时。

脚本中第一行总是"#!/bin/bash"或者直接"bash xyz.sh",这和上面的执行bash进入子shell其实是一回事,都是使用bash命令进入子shell。只不过此时的bash命令和情况②中直接执行bash命令所隐含的选项不一样,所以继承和加载的shell环境也不一样。事实也确实如此,它仅只继承父shell的某些环境变量,其余环境一概初始化

另外,执行shell脚本相比于直接执行bash命令,还多了一个动作:脚本执行完毕后自动退出子shell。

[root@linuxidc ~]# cat b.sh #!/bin/bash echo $BASHPID [root@linuxidc ~]# echo $BASHPID 65534 [root@linuxidc ~]# ./b.sh 65570

④.执行shell函数时。

其实shell函数就是命令,它和bash内置命令的情况一样。直接执行时不会进入子shell,但放在管道后会进入子shell。

[root@linuxidc ~]# fun_test (){ echo $BASHPID; } # 定义一个函数,输出BASHPID变量的值 [root@linuxidc ~]# echo $BASHPID 65230 [root@linuxidc ~]# fun_test # 说明执行函数不会进入子shell 65230 [root@linuxidc ~]# cd | fun_test # 但放在管道后会进入子shell 65605

⑤.执行非bash内置命令时。

例如执行cp命令、grep命令等,它们直接fork一份bash进程,然后使用exec加载程序替代该子bash。此类子进程会继承所有父bash的环境。但严格地说,这已经不是子shell,因为exec加载的程序已经把子bash进程替换掉了,这意味着丢失了很多bash环境。在bash文档中,直接称呼这种环境为"单独的环境",和子shell的概念类似。

[root@linuxidc ~]# let a=$BASHPID # let是内置命令 [root@linuxidc ~]# echo $a 65230 [root@linuxidc ~]# echo $BASHPID # echo是非内置命令,结果是不进入子shell 65230

⑥.命令替换。

当命令行中包含了命令替换部分时,将开启一个子shell先执行这部分内容,再将执行结果返回给当前命令。因为这次的子shell不是通过bash命令进入的子shell,所以它会继承父shell的所有变量内容。这也就解释了"echo $(echo $$)"中"$$"的结果是当前bash的pid号,而不是子shell的pid号,但"echo $(echo $BASHPID)"却和父bash进程的pid不同,因为它不是使用bash命令进入的子shell。

[root@linuxidc ~]# echo $BASHPID 65230 [root@linuxidc ~]# echo $(echo $BASHPID) # 使用命令替换$()进入子shell 65612

⑦.使用括号()组合一系列命令。

例如(ls;date;echo haha),独立的括号将会开启一个子shell来执行括号内的命令。这种情况等同于情况⑤。

[root@linuxidc ~]# echo $BASHPID 65230 [root@linuxidc ~]# (echo $BASHPID) # 使用括号()的命令组合进入子shell 65613

⑧.放入后台运行的任务

它不仅是一个独立的子进程,还是在子shell环境中运行的。例如"echo hahha &"。

[root@linuxidc ~]# echo $BASHPID 65230 [root@linuxidc ~]# echo $BASHPID & # 放入后台运行的任务进入子shell [1] 65614 [root@linuxidc ~]# 65614 [1]+ Done echo $BASHPID 

⑨.进程替换

既然是新进程了,当然进入子shell执行。例如"cat <(echo haha)"。

[root@linuxidc ~]# echo $BASHPID 65230 [root@linuxidc ~]# cat <(echo $BASHPID) # 进程替换"<()"进入子shell 65616

需要说明的是,子shell的环境设置不会粘滞到父shell环境,也就是说子shell的变量等不会影响父shell。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/13540.html