#!/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