-
2020-12-05 10:15:50
1、怎么理解shell并发:
当我们在执行一个for循环时,假设这个for循环需要循环500次,每循环一次就需要1秒,当这个for循环的脚本执行完毕时,就需要500秒,这样看效率有些低(尤其在量级高的时候,会更明显),所以我们需要shell脚本的for循环无论循环多少次,让它们同时执行,不需要按顺序循环,这就是shell脚本的并发。
2、如何实现shell脚本并发:
实现非常简单,就是在循环体的{}后面加上一个&符号,代表每次循环体的命令都放入后台运行
3、经典实例:
判断192.168.80.0/24网络,当前在线的主机数以及IP
#!/bin/bash . /etc/init.d/functions cmd="ping -c 2" for ((i=1;i<=254;i++));do { $cmd 192.168.80.$i &>/dev/null if [ $? = 0 ];then action "192.168.80.$i" /bin/true fi }& #将{}循环体放入后台执行 done wait #等待上面放入后台的命令执行完毕后,在往下执行(如果后面还有要执行的命令,最好加上wait),因为命令一旦放到后台执行,这条任务就交个操作系统了,shell脚本会不等上面的执行完毕,就会继续往下执行。
扩展知识点:
我们知道了什么是shell脚本的并发,试想一下,如果此时有1000个任务并发,就会有1000个线程产生,如果系统的资源跟不上,就会让计算机系统产生很大的压力,导致操作系统处理的速度会越来越慢。而此时我们又当如何解决呢?出现这个情况时,我们可以引入命名管道文件来处理。
命名管道处理的思路:
就相当于此时有10个开水房间,配有10把钥匙,此时有100个人要打开水,那么前10个人抢到钥匙,就先进去打开水,后面的90个人就需要等前面一个人出来后还回钥匙,在拿着钥匙进去打开水,这样就能控制100个人打开水的任务,同时不会将系统的资源一次性耗用太多,增加压力,减小处理速度。
知识点:
1、命名管道的特性
如果管道内容为空,则阻塞
管道具有读一个少一个,存一个读一个的性质,放回去的可以重复取
可以实现队列控制
如果管道放一段内容没有人取,则会阻塞
解决上述问题,可以通过文件描述符
文件描述符具有管道的所有特性,同时还具有一个管道不具有的特性:无限存不阻塞,无限取不阻塞,无需关注管道内容
创建方式:
1、创建命名管道mkfifo /tmp/fl
2、创建文件描述符100,并关联到管道文件
exec 100<>/tmp/fl
3、调用文件描述符,向管道里存放内容,同时也表示将用完的管道内容在放回管道
echo >&100
4、读取文件描述符关联管道中的内容
read -u100
5、关闭文件描述符的读和写
exec 100<&- exec 100>&-
实例演示:引用上面的网络测试案例
#!/bin/bash . /etc/init.d/functions cmd="ping -c 2" mkfifo /tmp/fl exec 100<>/tmp/fl rm -rf /tmp/fl for ((n=1;n<=100;n++));do echo >&100 done for ((i=1;i<=254;i++));do read -u100 { $cmd 192.168.80.$i &>/dev/null if [ $? = 0 ];then echo "192.168.80.$i is ok" else echo "192.168.80.$i is no" fi echo >&100 #将管道内容在放回去 }& done wait #echo "test compelet" exec 100<&- exec 100>&-
更多相关内容 -
Linux-Shell脚本并发及并发数的控制
2022-02-25 15:43:47需求:100个shell脚本任务,同时不超过20个并发执行,通过shell脚本实现。 使用linux管道文件特性制作队列,控制线程数目 知识储备: 一.管道文件 1:无名管道(ps aux | grep nginx) 2:有名管道(mkfifo /tmp/fd1)...需求:100个shell脚本任务,同时不超过20个并发执行,通过shell脚本实现。
使用linux管道文件特性制作队列,控制线程数目
知识储备:
一.管道文件
1:无名管道(ps aux | grep nginx)
2:有名管道(mkfifo /tmp/fd1)
有名管道特性:
1.cat /tmp/fd1(如果管道内容为空,则阻塞)实验:
2.echo “test” > /tmp/fd1(如果没有读管道的操作,则阻塞)
二.文件描述符1.管道具有存一个读一个,读完一个就少一个,没有则阻塞,放回的可以重复取,这正是队列特性,但是问题是当往管道文件里面放入一段内容,没人取则会阻塞,这样你永远也没办法往管道里面同时放入10段内容(想当与10把药匙),解决这个问题的关键就是文件描述符了。
- mkfifo /tmp/fd1
创建有名管道文件exec 3<>/tmp/fd1,创建文件描述符3关联管道文件,这时候3这个文件描述符就拥有了管道的所有特性,还具有一个管道不具有的特性:无限存不阻塞,无限取不阻塞,而不用关心管道内是否为空,也不用关心是否有内容写入引用文件描述符: &3可以执行n次echo >&3 往管道里放入n把钥匙
exec命令用法:exec命令用法
实现:
#!/bin/bash start_time=`date +%s` #定义脚本运行的开始时间 [ -e /tmp/fd1 ] || mkfifo /tmp/fd1 #创建有名管道 exec 3<>/tmp/fd1 #创建文件描述符,以可读(<)可写(>)的方式关联管道文件,这时候文件描述符3就有了有名管道文件的所有特性 rm -rf /tmp/fd1 #关联后的文件描述符拥有管道文件的所有特性,所以这时候管道文件可以删除,我们留下文件描述符来用就可以了 for ((i=1;i<=10;i++)) do echo >&3 #&3代表引用文件描述符3,这条命令代表往管道里面放入了一个"令牌" done for ((i=1;i<=1000;i++)) do read -u3 #代表从管道中读取一个令牌 { sleep 1 #sleep 1用来模仿执行一条命令需要花费的时间(可以用真实命令来代替) echo 'success'$i echo >&3 #代表我这一次命令执行到最后,把令牌放回管道 }& done wait stop_time=`date +%s` #定义脚本运行的结束时间 echo "TIME:`expr $stop_time - $start_time`" exec 3<&- #关闭文件描述符的读 exec 3>&- #关闭文件描述符的写
代码解析以及问题:
两个for循环,第一个for循环10次,相当于在女士公共厕所门口放了10把钥匙,第二个for
循环1000次,相当于1000个人来上厕所,read -u3相当于取走一把药匙,{}里面最后一行代码echo >&3相当于上完厕所送还药匙。
这样就实现了10把药匙控制1000个任务的运行,运行时间为101s,肯定不如方案二快,但是比方案一已经快很多了,这就是队列控制同一时间只有最多10个线程的并发,既提高了效率,又实现了并发控制。
注意:创建一个文件描述符exec 3<>/tmp/fd1 不能有空格,代表文件描述符3有可读(<)可写(>)权限,注意,打开的时候可以写在一起,关闭的时候必须分开关,exec 3<&-关闭读,exec 3>&-关闭写
-
shell脚本并发控制详解
2020-05-31 17:36:07shell并发控制 1.文件描述符 File Descriptors (FD,文件描述符或文件句柄):进程使用文件描述符来管理打开的文件 查看当前进程的fd 确定以下三点 如何exec打开一个文件 exec 3<> file1.txt 如何exec...shell并发控制
1.文件描述符
File Descriptors (FD,文件描述符或文件句柄):进程使用文件描述符来管理打开的文件
查看当前进程的fd
确定以下三点
如何exec打开一个文件
exec 3<> file1.txt
如何exec关闭一个文件(释放文件句柄)
如果没有释放句柄,文件删除后描述符依然还在
exec 3<&-
当一个文件FD未被释放,删除源文件也不会影响FD
rm -rf file1
cp /proc/$$/3 file1
[root@localhost my_scripts]# ll /proc/$$/fd 总用量 0 lrwx------ 1 root root 64 2月 11 11:35 0 -> /dev/pts/2 lrwx------ 1 root root 64 2月 11 11:35 1 -> /dev/pts/2 lrwx------ 1 root root 64 2月 11 11:35 2 -> /dev/pts/2 lrwx------ 1 root root 64 2月 11 14:07 255 -> /dev/pts/2 创建一个文件 touch /root/file1.txt exec 3<> /root/file1.txt 在当前进程打开这个文件,3代表文件描述符 将文件中输入内容 echo "123" >/proc/$$/fd/3 cat /root/file1.txt 这是123就会出现在file1中,因为描述符3打开了这个文件 删除/root/file1 rm -rf /root/file 这时ll /proc/$$/fd就会输出如下结果 [root@localhost my_scripts]# ll /proc/$$/fd 总用量 0 lrwx------ 1 root root 64 2月 11 11:35 0 -> /dev/pts/2 lrwx------ 1 root root 64 2月 11 11:35 1 -> /dev/pts/2 lrwx------ 1 root root 64 2月 11 11:35 2 -> /dev/pts/2 lrwx------ 1 root root 64 2月 11 14:07 255 -> /dev/pts/2 lrwx------ 1 root root 64 2月 11 11:35 3 -> /root/file1.txt (deleted) 表示这个文件已经被删除了 根据描述符恢复删除的文件 cp /proc/$$/fd/3 /root/file1 文件恢复 但是ll /proc/$$/fd/还是会提示3已经删除,这是由于每个文件都一个特定的iload编号 关闭当前进程的文件描述符 exec 3<&-
2.再谈管道
管道分为匿名管道和命名管道
我们平时用的|叫匿名管道,其实匿名管道也是一个文件,只不过他是在我们心目中的,而命名管道是名副其实的文件,由mkfifo命令创建一个命名管道文件,命名管道文件可以跨终端输入,只显示一次。
管道文件不会被覆盖,只有当有人读到这个文件才会消失
终端1 [root@localhost my_scripts]# mkfifo /tmp/fifo1 终端2 [root@localhost ~]# grep 'sda' /tmp/fifo1 等待输入 终端1 [root@localhost my_scripts]# ll /dev/ > /tmp/fifo1 终端2 brw-rw---- 1 root disk 8, 0 2月 10 21:36 sda brw-rw---- 1 root disk 8, 1 2月 10 21:36 sda1 brw-rw---- 1 root disk 8, 2 2月 10 21:36 sda2 获得内容 再次查看则内容小时,若想再看则重新定向到文件
3.并发控制实例
脚本实现多线程并发控制的原理:
首先定义并发的数量,然后创建管道文件,并往管道文件中插入数据(可以是空行),然后定义分隔符,以分隔符xx运行管道文件,在删除管道文件,因为删除管道文件不会影响句柄,在使用read -u命令读取分隔符内容,如果能读到数据则执行对应的后台进程,如果读取不到则一直等待,并发进程并不是等所有都执行完一轮后在执行新的一轮,而是完成一个后就会返回,比如控制 的并发数是50,那么始终都会是50个后台进程一起执行,直到程序结束
3.1.ping主机实现并发控制
#!/bin/bash #----------------------控制进程并发数量--------------------- #-------------shell多进程/多线程------------------ #定义控制并发的数量 bfsl=10 #定义管道文件 fifofile=/tmp/$$.fifo #创建管道文件 mkfifo $fifofile #以文件描述符3打开管道文件 exec 3<> $fifofile #删除管道文件,因为文件描述符打开的文件即使删除句柄也不会被释放 rm -rf $fifofile #循环往管道文件中写入内容 for i in $(seq $bfsl) do echo >&3 #这个表示只写入回车 done for i in {1..254} do read -u 3 #-u表示对文件描述符进行读取,如果能读取则执行下面的命令,如果不能则等待 { ip=192.168.81.$i ping -c1 -W1 $ip &>/dev/null if [ $? -eq 0 ];then echo "$ip is up" else echo "$ip is down" fi echo >&3 #由于之前是从管道文件中读走了一行,这里要在还回去一行,让后面的进程进行使用 }& done wait exec 3>&- #释放文件描述符 echo "finish.............."
3.2.创建用户实现并发控制
#!/bin/bash #------------创建用户实现并发控制------------ #------------shell多线程/多进程------------------- #并发数量,一次性能同时存在多少个进程 bfcs=50 #管道文件 fifofile=/tmp/user_$$.fifo #创建管道文件 mkfifo $fifofile #打开管道文件并定义为分隔符4 exec 4<> $fifofile #删除管道文件 rm -rf $fifofile #向管道文件插入空行 for i in $(seq $bfcs) do echo >&4 done for i in $(seq -w 1000) do read -u 4 #读取分隔符4,如果读到行则执行下面命令,否则一直等待 { user=qwe$i useradd $user echo "123" |passwd --stdin $user &>/dev/null if [ $? -eq 0 ];then echo "$user is created..." fi echo >&4 #当运行完命令后则重新向管道文件插入新的行,以便后续进程进行使用 }& done wait exec 4>&- #当所有循环完成后释放分隔符 echo "finish........."
-
Shell脚本并发运行(进程前后台运行)
2021-02-24 21:40:04介绍如何并发运行shell脚本的模部分代码实现效率提升,简单介绍所涉及的前后台运行知识并发运行
shell脚本一般运行模式就是按照脚本文件逐行运行,如例1:
#!/bin/bash for i in $(seq 1 6) do sleep 1 echo $i done echo "end <--" echo "time consume: ${SECONDS}s"
脚本总耗时6s
加入for循环里面的操作步骤没有前后依赖关系,为了提高效率可以在循环体中添加&将其改成并发运行模式,如例2:#!/bin/bash for i in $(seq 1 6) do { sleep 1 echo $i } & done wait #等待for循环结束后再运行后面指令 echo "end <--" echo "time consume: ${SECONDS}s"
当for循环数量庞大时,为了避免程序占用过多系统内存可以限制并发运行数量(比如最大并行数为3),如例3:#!/bin/bash # 创建有名管道 fd_file="/tmp/fd1" [ -e "${fd_file}" ] && rm -f "${fd_file}" mkfifo "${fd_file}" # 创建文件描述符,以可读(<)可写(>)的方式关联管道文件,这时候文件描述符3就有了有名管道文件的所有特性,linux启动后,会默认打开3个文件描述符,分别是:标准输入standard input 0,正确输出standard output 1,错误输出:error output 2,所以这里由3开始 exec 3<> "${fd_file}" # 关联后的文件描述符拥有管道文件的所有特性,所以这时候管道文件可以删除,我们留下文件描述符来用就可以了 [ -e "${fd_file}" ] && rm -rf "${fd_file}" #创建令牌 max=3 for i in $(seq 1 ${max}) do # echo 每次输出一个换行符,也就是一个令牌 echo >&3 done # read令牌,进行并发操作 for i in $(seq 1 6) do # read 命令每次读取一行,也就是拿到一个令牌 read -u3 { sleep 1 echo $i # 执行完一个循环体将令牌放回管道 echo >&3 } & done wait #等待for循环结束后再运行后面指令 exec 3<&- # 关闭文件描述符的读 exec 3>&- # 关闭文件描述符的写 echo "end <--" echo "time consume: ${SECONDS}s"
前后台运行
Linux系统进程前后台运行相关的几个命令:&、ctrl+z、jobs、fg、bg
- & 最经常被用到,用在一个命令或代码块的最后(注意需要空格隔开),可以把命令或代码段放到后台执行;
- ctrl + z 可以将一个正在前台执行的命令放到后台,并且暂停;
- jobs 查看当前后台运行的命令列表;
- fg 将后台中的命令调至前台继续运行;
- bg 将一个在后台暂停的命令,变成继续执行(后台运行);
以上面示例1的代码为例进行前后台运行调试结果如下,可以看到后台暂停运行的程序耗时还在继续计算中
-
shell脚本并发数据到kafka topic
2021-02-11 09:43:01shell脚本并发数据到kafka topic需求:每秒发送大量数据到kafka,验证下游系统性能,数据中的时间戳要求为当前时间,可以之间采集系统当前时间替换文件中旧的时间戳,保证每次发送的数据都为最新时间。利用kafka自带... -
Linux 限制shell脚本并发执行(通过flock对文件加锁)
2020-08-06 23:09:58一、flock声明 Usage: flock [options] <file>|<directory> <command> [<argument>...] flock [options] <file>|<directory>...Manage file locks from shell scripts. -
【Shell】Shell脚本并发与调试
2019-07-03 23:25:43Shell脚本里实现并发操作,需要用到 for循环 &后台运行符 wait等待所有子进程结束 思路: 我们可以通过写一个for循环,控制每次需要批量操作的次数,然后封装一个方法,方法里进行批量操作,并将此方法用&... -
并发数据库压力测试的shell脚本代码
2021-01-10 10:13:58/bin/bash#********************************##并发后台运行fun ##for wanggy 2012-01-25 ##note: ##fun_num fun函数后台运行次数 ##sql_num 每个函数sql运行次数 ##********************************##数据库... -
Shell脚本并发及并发数的控制
2018-11-14 14:56:38正常情况下,Shell脚本是串行执行的,一条命令执行完才会执行接下来的命令。如下代码: !/bin/bash for i in seq 1 10 do echo $i done echo “----end----” 脚本执行的结果如下: 1 2 3 4 5 6 7 8 9 10 ----end---... -
SHELL脚本并发问题一则记录
2017-06-19 08:32:43使用自动安装框架进行业务安装,调用SHELL脚本来修改权限等操作,包括修改server.xml配置等信息,某天两个安装任务一起运行时,发现密码字段为空,单独运行命令或单个安装任务则不会出现问题。 问题原因 SHELL代码... -
shell脚本并发执行
2019-09-22 16:36:201,shell脚本如何获取时间 2,shell脚本如何传入参数 3,shell脚本并发执行 转载于:https://www.cnblogs.com/rrttp/p/9056512.html -
linux shell脚本并发脚本
2019-03-25 23:33:00#!/bin/bash #开始时间 begin=$(date +%s) #测试根目录 if [ ! -d $root_dir ]; then mkdir -p $root_dir fi cd $root_dir #批量创建目录函数 function create_dir() ... /bin/bash /roo... -
shell脚本实现程序并发执行
2021-03-14 10:25:03shell脚本实现程序并发执行 循环实现并发程序: 并发的实现原理是将进程放到后台运行,从而不影响当前shell的运行。在shell脚本中有&符号可以实现这个操作。 # !/usr/bin/bash echo "hello multiprocess" for ... -
shell脚本中多线程和控制并发数量(包含同一脚本两个不同的并发数量)
2021-06-11 16:27:47正常执行 shell脚本中命令正常执行顺序是从上...多线程使命令并发执行,减少等待时间,使用wait作用等待所有在此shell脚本中启动的后台任务完成 #!/bin/bash for(( i = 0; i < ${count}; i++ )) do { commands1 -
shell脚本顺序执行和并发执行
2022-03-13 21:14:01https://blog.csdn.net/wangzhufei/article/details/87932048 Shell-使用&和wait让你的脚本并行执行 https://artisan.blog.csdn.net/article/details/87691890 -
shell实现并发控制
2021-09-30 13:17:50需求: 并发检测1000台web服务器状态(或者并发为1000台web服务器分发文件等)如何用shell实现? 方案-1:(单进程) 思路:一个for循环1000次顺序执行1000次任务。 #!/bin/bash start_time=`date +%s` #定义脚本... -
开发shell脚本并发请求S
2013-04-19 10:43:30编写shell脚本 将shell脚本放到应用模块下的bin目录下,如$FND_TOP/bin下,并将其从新命名为xxxx.prog文件 从shell脚本文件创建一个链接到$FND_TOP/bin/... -
shell控制多并发数量——脚本方法
2020-09-17 12:56:00但有一个问题,如果运行了好多个这样的脚本,都没释放,直到,达到系统设置的最大fd数,就打不开文件了。 也就是说,shell多进程,只有fd要释放这个潜在的危险,其它的风险都没有。但如果有fd要释放的,而没有弄限制... -
shell脚本多任务并发执行介绍(ping批量检测主机是否在线脚本)
2020-09-04 16:05:32文章目录说明非并发原理并发原理以ping某段主机是否在线对并发进行说明普通脚本 说明 非并发原理 一般脚本正常情况下执行过程是按顺序执行的,简单来说就是上一个执行完毕了才会进行下一个; 代码和执行结果如下: ... -
Shell脚本并发池控制
2018-09-20 16:37:54for tbname in $(impala-shell --quiet -B -q "use $dbname;show tables;"|cat) do read -u10 { echo "use $dbname;MSCK REPAIR TABLE ${tbname};" hive -v -e "use $dbname;MSCK REPAIR TABLE ${tbname};... -
SHELL脚本并发执行样例
2018-02-23 09:43:08/bin/bash# ----------------------------------------------------tmpfile=./$$.pid #$$是获取当前SHELL脚本进程的PIDmkfifo $tmpfile #生成一个FIFO管道文件exec 1000<>$tmpfile #绑定文件描述符... -
shell脚本实现多进程运行的方法示例
2020-09-15 08:37:49主要给大家分享了shell脚本实现多进程运行的方法示例,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。 -
shell 多进程并发(执行)脚本(fifo fd6)
2022-01-04 10:36:52shell多进程并发执行脚本 -
【Linux】Shell脚本中的多任务并发执行
2020-04-03 13:08:05Shell脚本中的多任务并发执行 需求 实现一个脚本能够使用ping检测网络的连通性 可以同时检测多个IP地址, 并且将检测结果输出 分析 正常情况下,Shell脚本中的命令是串行执行的,当一条命令执行完才会执行接下来的... -
Shell脚本中的多任务并发执行
2019-06-16 10:55:27正常情况下,Shell脚本中的命令是串行执行的,当一条命令执行完才会执行接下来的命令。比如下面这段代码: #!/bin/bash for i in {1..10};do echo $i done echo "END" 执行结果: 1 2 3 4 5 6 7 8 9 10 END 可以... -
一种限制shell脚本并行执行的方法
2018-07-24 21:28:21本发明公开了一种限制shell 脚本并行执行 的方法,应用于linux 和unix 平台,包括:当有 shell 脚本需要执行时,脚本模块...测脚本,来检测死锁,没有多个并发进程对同一个 令牌进行操作,可以有效地解决死锁的问题。