前段时间,我们一直在分享podman
基础知识,我感觉差不多了,收货慢慢,后面想介绍一下podman restful
,我们写一个基于容器的运维平台出来,不过只是构想,目前还在看demo
,余下还有时间,我们看看shell
,按照规矩,我们以某个点开头,本篇我们以linux shell
多进程打头。
什么是进程、进程、协程序
众所周知,在linux中是没有线程概念的,所以,linux只有进程概念
我自己的理解
什么是进程,线程,协程 他们的关系又是怎么样的?
进程是线程的集合
所以线程会共享进程的堆栈,故 线程可以使用进程的变量信息
线程是内核级别
协程是用户级别
CPU的核数 等于 内核线程的最大数量
在linux中实现简单的多进程
shell多进程需要注意的点
- 某些代码需要执行多进程的,需要放入后台执行,中间使用
{ 代码 }&
即可, 比如: 需要讲输出hello world
写成多进程的,这样的话,就会放在后入执行了
其实这也不难理解,因为我们通常要将执行命令放入后台,一般为: ./xxxx &
,脚本中也是类似的
顺序执行
执行结果
同时执行
执行结果
我们sleep
时间调整的长一些,我们可以看看具体进程树
我们执行成功后,看看进程树,使用命令ps axjf
可以看到其实我们对于shell
多进程,其实就是在系统中启用多个命令,仅此而已。
- 在执行多进程时,如果我们需要多进程执行完毕后再执行后续语句,那么,我们需要在多进程后面添加
wait
命令,此命令会等待后台进程执行完毕后再开始执行
我们尝试在脚本中加入wait
执行
我们可以看到,它其实是等待了3秒
这个到底有什么用? 我们通过例子说明
在linux shell中如何使用多进程错误案例
例子
有如下脚本
该脚本作用于将文件拷贝至backs
, 并且将其打包为tar.gz
格式
执行结果如下
执行完毕后,我们发现backs
目录中有数据,而backs.tar.gz
文件则为空的压缩包
这是因为我们循环中都放入后台运行了,且没有等待执行完毕,就执行打包操作,就造成了这样的局面,拷贝还没结束,打包就结束了,这样就有空包了,我们修改一下脚本,在循环结束后,加入一个wait
,这样该脚本才不会有问题
linux shell 控制进程数量
为什么我们需要控制进程数量
上述简单的多进程,能够帮助我们运维提高效率,但是也有致命缺陷,就是假设我们不知道循环次数的时候,贸然使用改脚本,则会出现问题,稍不注意就会饭碗不保,脚本如下
该脚本看上去好像没啥问题,但是我们忽略了一点,那就是数据库表
到底有多少? 每张表有多大?
假设该数据库下有1w
张表,每张表有100M
, 那我们在1s内建立1w
个连接去拉取数据库? 线上库都要玩蹦,抛出至理名言:“业务和我有一个能跑就成”?
所以基于上述原因,若无法预估执行次数,可能会导致服务器性能被压满,我们才需要控制脚本在后台中的数量。
在linux shell如何控制进程数量
我们将脚本简化一下,仅输出信息即可,稍后做出解释
执行效果如下
可以看到,程序是按照2个2个一组执行的
控制进程原理解析
创建管道文件
其实上面最主要的就是管道,众所周知,管道可以分为两种,1.匿名管道 2.命令管道 , 匿名管道就是我们最常见使用的 |
例如:ls -l | grep 123
,而使用mkfifo
则可以创建命令管道
exec
创建文件的标识符,系统中存在的标识符,为 0
,1
,2
即 stdin
,stdout
,stderr
, 代码中的 exec 1000<>/tmp/tests.fifo
其实定义的是输入和输出描述符,其标识符为1000
进程个数调节
这一步,它会首先向管道中写入2个值,可以发现这边是没有wait的,所以说,它会与下面并发执行
多进程本身
这个多进程语句和之前语句类似,唯一的不同是,多了一个往管道取值的动作还有复写管道的动作,以此来实现进程个数控制。
感想
在实际的运维工作中,很少使用shell 多进程
,原因是因为在多数情况下,用shell
编写的都是很简单的程序,什么时候需要用到shell
多进程呢? 正如上述所述,我们一般在备份数据、导入导出数据库的时候,使用多进程更多,但是我们一般会控制进程,毕竟,慢不要紧,要稳一点,如果把线上环境搞瞎了,可不好玩,作为一个运维小学生,我对运维行业,或者对线上正常跑的程序,始终都保持有敬畏之心,保证所有的命令,都是经过自己思考和确认的,避免引起误操作,哎呀,说多了,后期可以讲讲,运维有些误操作后,收拾起来有多恶心。