了解子 shell 和 父 shell 之间的关系以及一些命令
更多精彩
- 更多技术博客,请移步 IT人才终生实训与职业进阶平台 - 实训在线
5.1 shell 的类型
- Linux 中,用户使用的 shell 类型,被配置在 /etc/passwd 文件中,通常都是 bash shell
- 除了 bash shell ,CentOS 中一般还内置了 tcsh shell 、dash shell 、ash shell、tcsh shell
- 查看当前系统是否内置了上述 shell 类型,可以通过如下方式
- 可以看到,在下图的 CentOS 环境中,只存在 bash shell 和 dash shell
- 可以看到,在下图的 CentOS 环境中,只存在 bash shell 和 dash shell
- 但在 macOS 环境中,除了 ash shell 没有内置,其他的几种类型都可以找到
5.1.1 默认的系统 shell
- 在用户配置文件与用户绑定的 shell 会在系统启动时运行
- 但除了启动用户 shell 之外,还会启动一个系统 shell ,通常被指定为 /bin/sh ,如下图
- 但是可以看到,/bin/sh 只是 bash shell 的软链接
- 不过不是所有的系统的默认系统 shell 都指向 bash shell ,Ubuntu 通常会指向 dash shell
5.2 shell 的父子关系
- 父 shell 是指用于登录系统的默认 shell
- 子 shell 则是在 父 shell 环境中创建的其他 shell
- 使用
bash
命令可以在 父 shell 中创建 子 shell ,如下图-
ps -f
命令第一次执行时,只能获取两条进程信息,-bash 则是当前的 父 shell - 在执行
bash
命令后,再次执行ps -f
命令则获取到了三条进程信息,bash 则是刚才通过执行bash
命令创建的 子 shell -
bash 进程的 PPID 和 -bash 进程的 PID 一致,说明后者是前者的父级
-
-
bash
命令提供了一些指令,如下图
- 使用
exit
退出当前 shell ,如下图- 使用
bash
创建一个 子 shell 后 - 执行
exit
,再次执行ps -f
,之前创建的 子 shell 进程就不存在了
- 使用
- 子 shell 并不是真正的多进程处理,层级过多的 子 shell 会带来更多的系统花销,拖慢处理速度
5.2.1 进程列表
- 在介绍 进程列表 之前,需要先了解 命令列表
-
命令列表 是在多个命令之间通过分号分隔,让一行中的命令可以依次执行,如下图
-
可以看到,命令被依次执行并输出了结果
-
-
命令列表 想要进化成 进程列表 ,只需要在这些命令两侧加上括号即可,如下图
5.2.1.1 命令列表和进程列表的区别
- 那么你可能会问,只是加了括号,但输出结果一致,这两个列表的区别在哪
- 区别在于:命令列表 是直接执行这些命令串
- 但 进程列表 会创建一个 子 shell 开执行这些命令,执行完毕后 子 shell 也会随之结束
- 使用
echo $BASH_SUBSHELL
命令可以更清晰的知道命令在执行时,是否存在 子 shell ,如下图- 如果不存在,会返回 0 ,否则就是存在
- 返回数字的表达意思是 进程列表 的嵌套层级
5.2.2 别出心裁的子 shell 用法
5.2.2.1 & 命令探索后台模式
- 在后台模式中执行命令可以在处理命令的同时让出 CLI ,以供他用
- 在待执行命令的末尾添加字符
&
,可以让该命令在后台执行,如下图-
sleep 5
命令表示当前线程会等待 5 秒,如果直接执行,当前命令行会在 5 秒后才能继续接收输入 -
sleep 5 &
命令执行后则会立即返回一个后台任务 ID ,以及该进程的 PID ,当前命令行也可以立即接收新的输入 - 需要注意的是 macOS 在命令执行完毕后,会自动输出执行结果,如下图
- 但 CentOS 不会自动输出执行结果,需要再次执行
jobs
命令,才可以看到执行结果
-
5.2.2.2 jobs 命令查看后台进程
- 使用
jobs
命令可以显示当前运行在后台模式中的所有用户的进程信息 - 使用
jobs -l
则可以更详细的显示进程信息,如下图-
jobs
命令会显示后台进程的任务 ID 、PID 、进程状态、进程命令 - 同时当后台进程执行完毕后,也就无法通过
jobs
查看对应进程信息
-
5.2.2.3 将进程列表置入后台
- 将 进程列表 置入后台运行的好处在于:既可以在子 shell 中执行复杂的处理工作,又不会占用当前的 shell 窗口 ,如下图
5.2.2.4 coproc 命令实现协程
- 协程 是指在后台生成一个 子 shell ,并在这个 子 shell 中执行命令
- 使用
coproc
命令可以实现协程,如下图- 可以看到,使用
jobs
命令查看到的进程命令名称最后有一个&
符号,说明这也是一个后台进程
- 可以看到,使用
- 上图中大写的 COPROC 是在使用
coproc
命令时指定的默认协程名称 - 这个名称是可以自定义的,如下图
- 完整的语法是
coproc coprocName { command; }
-
命令中的花括号、空格、分号缺一不可,语法格式非常严格
- 完整的语法是
5.3 理解 shell 的内建命令
5.3.1 外部命令
- Linux 中存在 内建命令 和 外部命令 ,可以先理解一下 外部命令
- 外部命令 也被称为 文件系统命令 ,不是 shell 程序的一部分
- 外部命令 通常被放置在 /bin 、/usr/bin 、/sbin 、/usr/sbin 中
- 外部命令 在执行时,会创建一个子进程,在子进程中执行该命令,这个行为被称为 衍生( Forking )
5.3.1.1 which 命令和 type 命令查看命令归属
- 使用
which
命令和type
命令可以查看指定命令是属于 外部命令 ,还是 内建命令 ,如下图-
ps
命令位于 /bin 中,说明ps
命令就是 外部命令
-
5.3.2 内建命令
- 内建命令 和 外部命令 的区别在于,内建命令 不需要使用子进程来执行命令
- 内建命令 和 shell 是一体的,作为 shell 工具的组成部分而存在
- 内建命令 因为不需要通过衍生行为来执行,所以执行速度会更快、效率更高
- 使用
which
命令和type
命令也可以查看该命令是否属于 内建命令 ,如下图- 可以看到,
cd
exit
pwd
命令都属于 内建命令
- 可以看到,
5.3.2.1 type -a 命令查看命令的多种实现
- 有些命令存在多种实现,使用
type -a
可以将该命令的全部实现列举出来,如下图- 可以看到,
pwd
echo
命令既是 内建命令 ,也在 /bin 目录中有一份实现
- 可以看到,
5.3.2.2 history 命令查看使用过的历史命令
- 首先
history
命令是一个 内建命令 - 可以通过
history
命令查看之前使用过的命令,如下图- 在 CentOS 中,
history
命令默认最多可以存储 1000 条历史命令,但这个值可以通过 HISTSIZE 的环境变量进行修改 - 下图中只列出了 6 条数据,是因为为了方便显示,使用
history -c
命令删除了之前的所有历史数据
- 在 CentOS 中,
5.3.2.3 !! 命令直接执行最近一条历史命令
- 使用
!!
命令可以直接在新的一行显示出上一条刚刚执行过的命令,如下图-
!!
命令执行之后,在下一行出现的pwd
命令不是手动输入的,而是由!!
命令呼出的 -
呼出的命名不会直接执行,只是显示出来,需要手动按回车键,才能再次执行该命令
-
5.3.2.4 在 .bash_history 文件中查看命令历史记录
- 使用
history
命令查看的命令历史记录,被存放在根目录的 .bash_history 文件中 - 需要注意的是,命令的历史记录并不是直接存放到该文件,而是先存放到内存中,当 shell 退出时,才被写入到该文件
- 想要强制将命令历史记录写入文件中,可以使用
history -a
命令
5.3.2.5 alias 命令实现为命令指定别名
-
alias
命令也是一个 内建命令 - 需要注意的是,直接使用命令创建的别名,只能在当前会话生效,无法做到全局生效
- 想要全局生效,则需要将别名写入配置文件中,后续章节会有介绍
- 使用
alias
命令可以为某个复杂的命令指定一个简单的别名,从而将调用命令的输入减少到最低,如下图- 可以看到,通过
alias
命令将ls -al
命令指向ll
命令 - 之后再输出
ll
命令,就可以得到和ls -al
命令一样的结果
- 可以看到,通过
5.3.2.6 alias -p 命令查看当前有多少命令别名
- 使用
alias -p
命令可以列出当前系统中存在哪些命令别名可以使用,如下图
- 上图是 CentOS 的效果,如果是 macOS ,无法使用
alias -p
命令,直接使用alias
命令,不加任何后缀即可
5.4 小结
- shell 之间存在父子级关系
- 使用
bash
命令可以创建 子 shell - 使用
exit
命令可以退出 子 shell - 使用
&
命令可以将命令置入后台 - 使用
coproc
命令可以在子进程中执行命令 - 命令列表 是指在多个命令之间添加分号,可以依次执行命令
- 进程列表 是指在 命令列表 外部添加一对括号,可以将这些命令在子进程中执行
- 使用
history
命令可以查看命令历史记录 - 使用
!!
命令可以快速呼出最近依次的命令历史记录 - 使用
alias
命令可以给长命令指定短别名
网友评论