Bash 子 shell

Bash 子 shell

什么是子 shell

子 shell 是指在操作系统中创建的一个新的 shell 进程,它是由父 shell(父进程)派生出来的。子 shell 可以独立运行,但它仍然受到父 shell 的控制和影响。子 shell 可以执行与父 shell 不同的命令和操作,但在子 shell 中所做的更改不会影响到父 shell 或其他子 shell。

子 shell 通常用于在父 shell 的环境中执行一系列命令,而不会影响到父 shell 的状态。这对于需要进行一些临时性的操作、测试或脚本执行非常有用。当子 shell 执行完毕后,控制权会返回到父 shell。

子 shell 和父 shell 的关系其实就是子进程和父进程的关系,子 shell 会从父 shell 中继承很多环境,如变量、命令全路径、文件描述符、当前工作目录、陷阱等等,但子 shell 有很多种类型,不同类型的子 shell 继承的环境不相同。

可以使用 $BASH_SUBSHELL 变量来查看从当前进程开始的子 shell 层数,$BASHPID 查看当前所处 BASH 的 PID,这不同于特殊变量 $$,因为 $$ 在大多数情况下都会从父 shell 中继承。

$$ 变量保存的是当前 shell 进程 ID 号

如何产生子 shell?

参考博客:子 shell 以及什么时候进入子 shell - 骏马金龙 - 博客园

首先 shell 进程本质上是 Linux 进程,Linux 创建子进程的方式有三种:

为了保证进程安全,若要形成新的且独立的子进程,都会先 fork 一份当前进程,然后在 fork 出来的子进程上调用 exec 来加载新程序替代该子进程。例如在 bash 下执行 cp 命令,会先 fork 出一个 bash,然后再 exec 加载 cp 程序覆盖子 bash 进程变成 cp 进程。

何时产生子 shell?

那什么情况下会进入子 shell 环境,什么时候不进入子 shel 环境呢?

判断是否进入了子 shell 的方式非常简单,执行 echo $BASHPID,如果该值和父 bash 进程的 pid 值不同,则表示进入了子 shell。

再说明 $$ 的继承问题。除了直接执行 bash 命令和 shell 脚本这两种子 shell,其他进入子 shell 的情况都会继承父 shell 的值。前面也已经说了,其实 shell 脚本和直接执行 bash 命令开启子 shell 的方式是一样的,它们都不会继承 "$$" 值,可以根据上述实验自行测试。

需要说明的是,子 shell 的环境设置不会粘滞到父 shell 环境,无论是使用 export 还是 source ,都只能是父 shell 同步到子 shell,不是也不会是从子 shell 同步到父 shell。也就是说子 shell 的变量等不会影响父 shell。