红联Linux门户
Linux帮助

关于Linux shell多线程控制无效的bug

发布时间:2016-06-06 16:07:01来源:linux网站作者:Adel

shell的多线程编程代码网上有很多,示例代码如下:

thead_num=5 #设置线程数,在这里所谓的线程,其实就是几乎同时放入后台(使用&)执行的进程。
tmp_fifo_file="/tmp/$$.fifo"  #以进程ID号命名管道文件
mkfifo $tmp_fifo_file   #创建临时管道文件
exec 6<>$tmp_fifo_file  #以读写方式打开tmp_fifo_file管道文件,文件描述符为6,也可以取3-9任意描述符
rm -f $tmp_fifo_file    #删除临时管道文件,也可不删除

for ((i=0;i<$thead_num;i++))   #利用for循环向管道中输入并发数量的空行
do
echo ""  #输出空行
done >&6  #输出重导向到定义的文件描述符6上

for i in $ip  #循环所有要执行的服务器
do
read -u6  #从管道中读取行,每次一行,所有行读取完毕后执行挂起,直到管道有空闲的行
{
......  #线程内的执行代码(如果需要执行时间较长,bug就可能来了)
echo "" >&6  #再写入一个空行,使挂起的循环继续执行
}&  #放入后台执行
done
wait  #等待所有后台进程执行完成
exec 6>&-  #删除文件描述符


问题:之前遇到过一个很惊艳的bug,在用shell写多线程时,线程数量在达到设定的数量之后继续不断增加,多线程控制是无效的,这bug也简直了,我明明给了5个并发,这丫的愣是创建了几十个进程,结果发现查了好多资料,愣是没找到原因,后来发现是我的每个线程处理块的执行时间都比较久,结果,正在 执行的进程还没执行结束,也就是管道中还没有新的空闲的行,系统就新创建了一个新的进程,这看似很不合逻辑。


解决办法:用“read -u6 -t86400”替换“read -u6”,-t后面的数字表示时间,单位是秒


原因:具体权威的原因不太确定,根据已知的资料,推测是因为read -u6这条命令的[ -t ]参数是有默认值的,在我的系统里 ,好像是3min,也就是说,如果3min之后,后台进程依然没有执行结束,系统会认为该进程已经执行完毕,继续分配进程。需要特别说明的是,不是所有的系统都需要指定这个[ -t ]参数的,具体跟操作系统有关。以上原因为个人推测。


本文永久更新地址:http://www.linuxdiyf.com/linux/21300.html