#!/bin/bash
#取出网站数据
web=`cat website.txt`
if [ -z "$web" ];then       #判断长度如果为0,则为真。没有需要测试网站
    echo "Data that is not tested"
    exit 1
fi
test -f result.log && rm -f result.log  #test -f 如果是一个普通文件则为真
function delay {
    sleep 3
}
tmp_fifofile=/tmp/$$.fifo  #声明管道名称,'$$'表示脚本当前运行的进程PID
mkfifo $tmp_fifofile         #创建管道
exec 6<>$tmp_fifofile     #创建文件标示符“5”,这个数字可以为除“0”、“1”、“2”之外的所有未声明过的字符
rm $tmp_fifofile              #清除创建的管道文件
#定义并发线程数,需根据vps配置进行调整。
thread=100
for ((i=0 ;i<$thread;i++ ))
do
    echo ; #借用read命令一次读取一行的特性,使用一个echo默认输出一个换行符,来确保每一行只有一个线程占位;这里让人联想到生产者&消费者模型,管道文件充当消息队列,来记录消费者的需求,然后由生产者去领任务,并完成任务,这里运用了异步解耦的思想。
done>&6 #将占位信息写入管道
#开始多线程循环检测
for url in $web
do
    read -u6 #从文件描述符管道中,获取一个管道的线程占位然后开始执行操作;read中 -u 后面跟fd,表示从文件描述符中读入,该文件描述符可以是exec新开启的。
    {
    #curl抓取网站http状态码
    code=`curl -o /dev/null --retry 3 --retry-max-time 8 -s -w %{http_code} $url`
    echo "$code ---> $url">>result.log
    #判断子线程是否执行成功,并输出结果
    delay && {
        echo "$code ---> $url"
    } || {
        echo "Check thread error!"
    }
    echo >& 6 #任务执行完后在fd5中写入一个占位符,以保证这个线程执行完后,线程继续保持占位,继而维持管道中永远是100个线程数,&表示该部分命令/任务放入后台不占当前的bash,实现并行处理
}&
done
#等待所有线程执行完毕
wait
exec 6>&- #关闭fd6的管道
#找出非200返回码的站点
echo List of exception website:
cat result.log | grep -v 200
exit 0