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>&-