shell实践

shell实践

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CXbAtF5F-1678231899581)(http://book.luffycity.com/linux-book/Shell%E5%9F%BA%E7%A1%80/pic/image-20210301155751435.png)]

父子shell

父shell:我们在登录某个虚拟机控制器终端的时候(连接某一个linux虚拟机)时,默认启动的交互式shell,然后等待命令输入。

ps命令参数,是否有横杠的参数作用是不一样的

-f  显示UID,PPID,C与STIME栏位。
f  用ASCII字符显示树状结构,表达进程间的相互关系。

-e  此参数的效果和指定"A"参数相同。
e  列出进程时,显示每个进程所使用的环境变量。

案例

1.于超老师登录自己的虚拟机
[yuchao@yumac Luffy_linux]$sshpyyu
Last login: Sat Sep 26 21:06:16 2020 from 221.218.215.96
[root@chaogelinux ~]#

2.一条命令,查看进程的父子关系
[root@chaogelinux ~]# ps --forest -ef
# 观察如下信息,可以清晰看出父子关系
root      1830     1  0 9月25 ?       00:00:00 /usr/sbin/sshd -D
root     15105  1830  0 21:07 ?        00:00:00  \_ sshd: root@pts/0
root     15107 15105  0 21:07 pts/0    00:00:00      \_ -bash
root     16074 15107  0 21:11 pts/0    00:00:00          \_ ps --forest -ef

子shell

当在CLI的提示符下,输入/bin/bash指令,或者其他bash指令,会创建一个新的shell程序,这就被称之为子shell(child shell)

子shell同样的拥有CLI提示符,可以输入命令。

使用如下命令,超哥教你如何查看父子的诞生

[root@chaogelinux ~]# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     15107 15105  0 21:07 pts/0    00:00:00 -bash
root     16893 15107  0 21:17 pts/0    00:00:00 ps -f

当前父shell   15107
[root@chaogelinux ~]# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     15107 15105  0 21:07 pts/0    00:00:00 -bash
root     16966 15107  1 21:18 pts/0    00:00:00 bash
root     17144 16966  0 21:18 pts/0    00:00:00 ps -f

第一次父bash的pid,15107
第二次执行bash,子shell的pid, 16966,ppid是15107,由此看出是子shell

输入bash指令之后,一个子shell就产生了。

  • 第一个ps -ef命令是在父shell里执行的
  • 第二个ps -ef是在子shell里执行的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ezt1f4qd-1678231899584)(http://book.luffycity.com/linux-book/Shell%E5%9F%BA%E7%A1%80/pic/image-20200927092127774.png)]

子shell生成时,父进程的部分环境变量被复制到子shell里,这个后面于超老师在给大家说。

多个子shell

1.当前shell关系
root      1830     1  0 9月25 ?       00:00:00 /usr/sbin/sshd -D
root     22206  1830  0 09:23 ?        00:00:00  \_ sshd: root@pts/2
root     22208 22206  0 09:23 pts/2    00:00:00      \_ -bash
root     22757 22208  0 09:24 pts/2    00:00:00          \_ ps -ef --forest


2.执行多个bash,开启多个子shell
连续输入四次bash之后

root      1830     1  0 9月25 ?       00:00:00 /usr/sbin/sshd -D
root     22206  1830  0 09:23 ?        00:00:00  \_ sshd: root@pts/2
root     22208 22206  0 09:23 pts/2    00:00:00      \_ -bash
root     22844 22208  0 09:25 pts/2    00:00:00          \_ bash
root     23017 22844  0 09:25 pts/2    00:00:00              \_ bash
root     23190 23017  1 09:25 pts/2    00:00:00                  \_ bash
root     23363 23190  1 09:25 pts/2    00:00:00                      \_ bash
root     23537 23363  0 09:25 pts/2    00:00:00                          \_ ps -ef --forest

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m2ZiWnAi-1678231899585)(http://book.luffycity.com/linux-book/Shell%E5%9F%BA%E7%A1%80/pic/image-20200927092630728.png)]

退出子shell

exit 可以退出子shell,也可以退出当前的虚拟控制台终端。
只需要在父shell里输入exit就可以退出了。

进程列表(创建子shell)

若是超哥想要执行一系列的命令,可以通过命令列表来实现,如下

[root@chaogelinux ~]# pwd;ls;cd /opt;pwd;ls
这样的写法,命令的确会依次执行,但是这并不是【进程列表】

必须如下写法才是

[root@chaogelinux opt]# (cd ~;pwd;ls ;cd /tmp;pwd;ls)

命令列表,必须写入括号里,进程列表是生成子shell去执行对应的命令。

进程列表的语法就是如上

(command1;command2)

检测子shell

通过一个环境变量,检查子shell是否存在

[root@chaogelinux opt]# echo $BASH_SUBSHELL
0

结尾为0则没有子shell,非0就是有子shell

非子shell的执行命令

[root@chaogelinux opt]# cd ~;pwd;ls ;cd /tmp;pwd;ls;echo $BASH_SUBSHELL
能够看到结果为0,表示是父shell直接执行

子shell的执行形式

[root@chaogelinux tmp]# (cd ~;pwd;ls ;cd /tmp;pwd;ls;echo $BASH_SUBSHELL)
看到结果不为0了,表示是在子shell里运行了

子shell嵌套

刚才我们是用了一个括号,开启子shell,现在可以开启多个子shell
[root@chaogelinux tmp]# (pwd;echo $BASH_SUBSHELL)
/tmp
1


细心的同学观察下,超哥这里是怎么改动的
[root@chaogelinux tmp]# (pwd;(echo $BASH_SUBSHELL))
/tmp
2

观察到环境变量的数字已经发生了变化,其实是通过两个括号,创建了2个子shell。

shell脚本开发里,经常会使用子shell进行多进程处理。

后台执行与子shell

在我们日常shell命令执行里,很多地方都有用到子shell,如进程列表、协程、管道等。

一个高效的子shell用法是和后台结合使用。

使用sleep命令

sleep 3
sleep将你会话暂停3秒,然后返回shell

不希望sleep卡住会话,将它放在后台

[root@chaogelinux tmp]# sleep 300&
[1] 27520

显示的是后台作业的id号(background job  1),以及后台进程的PID(27520)

[root@chaogelinux tmp]# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     24734 24731  0 09:36 pts/2    00:00:00 -bash
root     27520 24734  0 09:57 pts/2    00:00:00 sleep 300
root     27557 24734  0 09:57 pts/2    00:00:00 ps -f

我们发现是基于bash父shell的24734生成的27520

jobs命令

[root@chaogelinux tmp]# jobs
[1]+  运行中               sleep 300 &
[root@chaogelinux tmp]#

jobs命令可以显示后台作业信息

[root@chaogelinux tmp]# jobs -l
[1]+ 27520 运行中               sleep 300 &

显示pid信息

一旦后台jobs完成,就会显示出结束状态。
[1]+  完成                  sleep 300

进程列表放入后台

先看一个事例

[root@chaogelinux tmp]# (sleep 2;echo $BASH_SUBSHELL;sleep 2)
1
这个案例,会有2秒的暂停,显示数字,表示只有一个子shell,然后又暂停了2秒,最终返回提示符

在看下进程列表,结合后台模式的效果

[root@chaogelinux tmp]# (sleep 2;echo $BASH_SUBSHELL;sleep 2)&
[1] 29308
[root@chaogelinux tmp]# 1

[1]+  完成                  ( sleep 2; echo $BASH_SUBSHELL; sleep 2 )

这样的子shell用法,目的是在于,开辟子shell处理繁琐的工作,同时保证不会让子shell限制终端的使用。

我们会在后面学习结合tar命令进行后台压缩的实用案例。

# 这里注意,tar压缩的时候,会有报警信息,原因是绝对路径的问题,可以忽略,是系统为了保护文件的操作

[root@chaogelinux tmp]# (tar -cf Tmp.tar /tmp;tar -Pcf Home.tar /home)&
[1] 29931

此时可以通过命令检查,父子shell的执行方式

[root@chaogelinux tmp]# ps -ef --forest
root      1830     1  0 9月25 ?       00:00:00 /usr/sbin/sshd -D
root     24731  1830  0 09:36 ?        00:00:00  \_ sshd: root@pts/2
root     24734 24731  0 09:36 pts/2    00:00:00      \_ -bash
root     30337 24734  0 10:28 pts/2    00:00:00          \_ -bash
root     30341 30337 16 10:28 pts/2    00:00:02          |   \_ tar -cf Tmp.tar /tmp
root     30452 24734  1 10:28 pts/2    00:00:00          \_ ps -ef --forest

协程与子shell

协程也是在后台创建子shell,然后在子shell中执行命令

# 使用coproc命令
[root@chaogelinux tmp]# coproc sleep 10
[1] 31253
[root@chaogelinux tmp]#
[root@chaogelinux tmp]#
[root@chaogelinux tmp]#
[1]+  完成                  coproc COPROC sleep 10


[root@chaogelinux tmp]# ps -ef --forest
root      1830     1  0 9月25 ?       00:00:00 /usr/sbin/sshd -D
root     24731  1830  0 09:36 ?        00:00:00  \_ sshd: root@pts/2
root     24734 24731  0 09:36 pts/2    00:00:00      \_ -bash
root     31404 24734  0 10:34 pts/2    00:00:00          \_ sleep 10
root     31440 24734  0 10:34 pts/2    00:00:00          \_ ps -ef --forest

协程是将命令放在后台执行,也可以通过jobs命令看到

[root@chaogelinux tmp]# coproc sleep 10
[1] 31610
[root@chaogelinux tmp]# jobs
[1]+  运行中               coproc COPROC sleep 10 &

协程给任务起了个名字,COPROC,也可以自己指定名字

[root@chaogelinux tmp]# coproc Chao_ge_job { sleep 10; }
[1] 31840
[root@chaogelinux tmp]# jobs
[1]+  运行中               coproc Chao_ge_job { sleep 10; } &

通过这种写法,协程的名字指定了,注意扩展语法{ 任务 }花括号里面的空格。

内建命令

这里超哥曾经在15年在上海面试运维的时候,面试官问过这个问题:你知道linux内置命令,外置命令吗?

答:

> >

内置命令:在系统启动时就加载入内存,常驻内存,执行效率更高,但是占用资源

外置命令:用户需要从硬盘中读取程序文件,再读入内存加载

外部命令

外部命令也称作文件系统命令,存在于bash shell之外的程序,一般存在的路径是

/bin
/usr/bin
/sbin/
/usr/sbin

例如ps就是外部命令

[root@chaogelinux tmp]# which ps
/usr/bin/ps

[root@chaogelinux tmp]# type -a ps
ps 是 /usr/bin/ps

[root@chaogelinux tmp]# ls -l /usr/bin/ps
-rwxr-xr-x 1 root root 100112 10月 19 2019 /usr/bin/ps

外部命令在执行时,会创建一个子进程,我们还是可以通过ps命令查看,进程id号

[root@chaogelinux tmp]# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root       750 24734  0 10:45 pts/2    00:00:00 ps -f
root     24734 24731  0 09:36 pts/2    00:00:00 -bash

ps命令是父bash,创建新的进程750执行的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mYacZkVP-1678231899586)(http://book.luffycity.com/linux-book/Shell%E5%9F%BA%E7%A1%80/pic/image-20200927104612601.png)]

无论是子进程,还是子shell,我们都可以通过发送signaling信号和其沟通。

内置命令

内置命令和外置命令的区别,就在于是否会创建子进程去执行

内置命令和shell编译为一体,是shell的一部分,不需要外部程序文件执行。

还是可以通过type了解命令是否是内建的。

[root@chaogelinux tmp]# type cd
cd 是 shell 内嵌
[root@chaogelinux tmp]# type exit
exit 是 shell 内嵌

因为内置命令不需要衍生子进程执行,也不用打开程序文件,执行速度更快,效率也更高。

查看内置命令

# 该命令列出所有的bash shell可以用的内置命令
[root@web01 ~ 11:33:33]$compgen -b

查看外置命令

除了以上的内置命令,日常使用的大部分命令都是外部命令啦。

可以用type验证下即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值