#!/bin/bash
# 接受信号2(ctrl+C)
# 关闭fd 6的绑定
# 注意:绑定时可以用 exec <> fifofile;
# 但关闭时必须分开写:exec 6>&-和exec 6<&- 是关闭fd6
trap "exec 6>&-; exec 6<&-; exit 0" 2
# 管道文件名
tempfile="temp.$$"
# 创建有名管道
# 管道的特点:
# 1. 如果管道中没有数据,则读管道数据的操作会阻塞,直到管道内写入数据
# 2. 管道内有数据,如果没有读取操作也会阻塞,直到读取后才会终止这一操作
mkfifo ${tempfile}
# 绑定文件操作符为管道
exec 6<>${tempfile}
# fd6已绑定成为管道,不再需要管道文件,可直接删除掉
rm -f ${tempfile}
# 并发执行线程数
tnum=10
preip="192.168.100."
# 对文件操作符进行写入操作,通过for循环写入$tnum个空行,即为后台线程数量
for ((i=1; i<=$tnum; i++)); do
{
echo >&6
}
done
for ip in $(seq 2 254); do
{
# 从文件操作符读取管道中的一个空行
read -u 6
{
# 并发操作代码块
sleep 1
ping -q -c2 -W1 "${preip}$ip" &>/dev/null
if [ $? -eq 0 ]; then
echo -e " 33[32m${preip}$ip is alive. 33[0m"
else
echo -e " 33[31m${preip}$ip is down. 33[0m"
fi
# 重点:读取完一个空行后,重新向文件操作符写入一个空行,
# 否则当$tnum个任务放入后台后,由于操作符中没有可读取的空行,导致read -u 6阻塞
echo >&6
}& # 将任务放入后台执行
}
done
# 等待所有线程执行完毕,避免主进程提前退出
wait
# 关闭文件操作符的读写绑定
exec 6>&-
exec 6<&-