linux中shell模拟多线程执行任务详解
发布:smiling 来源: PHP粉丝网 添加日期:2015-04-25 14:49:21 浏览: 评论:0
多线程是对于linux系统来讲是小菜了,下面小编为各位整理一篇linux中shell模拟多线程执行任务详解,希望文章可以帮助到各位。
shell本身是不能实现多线程的,但是可以通过启动子进程,并将子进程放入后台执行来模拟多线程,为了在提高脚本执行效率的同时又不明显增加负载的作用,还需要对同时放入后台的进程数做下限制,代码如下:
- #!/bin/bash
 - set -x # 开启调试模式
 - #判断是否有参数
 - if [ $# != 1 ];then
 - echo "您输入的参数有误"
 - exit -1
 - fi
 - # 允许的最大进程数
 - MAX_THREAD_NUM=5
 - tmp_fifo_file=/tmp/$$.fifo # 以脚本运行的当前进程ID号作为文件名
 - mkfifo "$tmp_fifo_file" # 新建一个随机fifo管道文件
 - exec 9<>"$tmp_fifo_file" # 定义文件描述符9指向这个fifo管道文件
 - rm "$tmp_fifo_file"
 - # 预先写入指定数量的换行符到fifo管道文件中,一个换行符代表一个进程
 - for((i=0;i<$MAX_THREAD_NUM;i++));do
 - echo
 - done >&9
 - # 循环读出url并判断状态码
 - while read line
 - do
 - {
 - # 进程控制
 - read -u 9 # 从文件描述符9中读取行,实际指向fifo管道
 - {
 - isok=`curl -I -L -m 60 -o /dev/null -s -w %{http_code} $line`
 - if [ "$isok" = "200" ];then
 - echo $line "OK"
 - else
 - echo $line $isok
 - fi
 - echo >&9 # ,当前进程结束,往fifo管道文件中写入一个空行
 - }& //phpfensi.com
 - }
 - done < $1 wait echo '执行结束' exec 9>&- # 删除文件描述符9
 - exit 0
 
脚本的任务是对一个url列表中的网址进行判断,判断这些网址是否可以继续访问,具体方法是,通过curl获取http的状态码来判断.
上面红色部分{}中的语句被放进子进程中在后台执行,当fifo中5个空行读完后,循环继续等待 read 中读取fifo数据,当后台的子进程完成任务后,排队往fifo输入空行,这样fifo中又有了数据,循环继续执行.
下面看看shell执行的结果,代码如下:
- # bash scanUrl.sh url.txt
 - + '[' 1 '!=' 1 ']'
 - + MAX_THREAD_NUM=5
 - + tmp_fifo_file=/tmp/phpfensi.com
 - + mkfifo /tmp/phpfensi.com
 - + exec
 - + rm /tmp/phpfensi.com
 - + (( i=0 ))
 - + (( i<5 ))
 - + echo
 - + (( i++ ))
 - + (( i<5 ))
 - + echo
 - + (( i++ ))
 - + (( i<5 ))
 - + echo
 - + (( i++ ))
 - + (( i<5 ))
 - + echo
 - + (( i++ ))
 - + (( i<5 ))
 - + echo
 - + (( i++ ))
 - + (( i<5 ))
 - + read line
 - + read -u 9
 - ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://phpfensi.com /
 - + read line
 - + read -u 9
 - ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://phpfensi.com /
 - + read line
 - + read -u 9
 - ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://phpfensi.com /
 - + read line
 - + read -u 9
 - ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://phpfensi.com /
 - + read line
 - + read -u 9
 - ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://phpfensi.com /
 - + read line
 - + read -u 9 # fifo文件中的5个空行读完了,等待其它子进程写入fifo
 - + isok=200
 - + '[' 200 = 200 ']'
 - + echo http://phpfensi.com / OK
 - http://phpfensi.com / OK
 - + echo # 这个子进程完成任务,写入fifo一个空行,启动一个子进程
 - ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://phpfensi.com /
 - + read line
 - + read -u 9
 - + isok=200
 - + '[' 200 = 200 ']'
 - + echo http://50vip.com/ OK
 - http://50vip.com/ OK
 - + echo
 - ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://phpfensi.com /info/
 - + read line
 - + read -u 9
 - + isok=200
 - + '[' 200 = 200 ']'
 - + echo http://361a.net/ OK
 - http://361a.net/ OK
 - + echo
 - ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://phpfensi.com /
 - + read line
 - + wait # 输入文件中的url都已经处理完成或在子进程中处理,等待所有子进程结束
 - + isok=200
 - + '[' 200 = 200 ']'
 - + echo http://phpfensi.com / OK
 - http://phpfensi.com / OK
 - + echo
 - + isok=000
 - + '[' 000 = 200 ']'
 - + echo http://5imovie.org/ 000
 - http://5imovie.org/ 000
 - + echo
 - + isok=200
 - + '[' 200 = 200 ']'
 - + echo http://phpfensi.com / OK
 - http://52ixwebhosting.com/ OK
 - + echo
 - + isok=404
 - + '[' 404 = 200 ']'
 - + echo http://phpfensi.com /info/ 404
 - http://phpfensi.com /info/ 404
 - + echo
 - + isok=000
 - + '[' 000 = 200 ']'
 - + echo http://phpfensi.com / 000
 - http://42.hcocoa.com/ 000
 - + echo
 - + echo $'346211247350241214347273223346235237'
 - 执行结束
 - + exec
 - + exit 0
 
下面我们再来看个例子,代码如下:
- #!/bin/bash
 - function pinghost {
 - ping $1 -c 1 -w 10 |grep rtt|cut -d “/” -f6
 - }
 - tmp_fifofile=”/tmp/$.fifo” # 脚本运行的当前进程ID号作为文件名
 - mkfifo $tmp_fifofile # 新建一个随机fifo管道文件
 - exec 6<>$tmp_fifofile # 定义文件描述符6指向这个fifo管道文件
 - rm $tmp_fifofile
 - thread=10
 - for ((i=0;i<$thread;i++));do # for循环 往 fifo管道文件中写入10个空行
 - echo
 - done >&6
 - while read domain
 - do
 - read -u6 # 从文件描述符6中读取行(实际指向fifo管道)
 - {
 - pinghost ${domain}; # 执行pinghost函数
 - echo >&6 # 再次往fifo管道文件中写入一个空行。
 - }& # 放到后台执行
 - done</home/miotour/ip.txt
 - wait #因为之前的进程都是后台执行,因此要有wait来等待所有的进程都执行完毕后才算整个脚本跑完。
 - exec 6>&- #删除文件描述符6
 - exit 0
 
说明:{} 这部分语句被放入后台作为一个子进程执行,这部分几乎是同时完成的,当fifo中10个空行读完后 while循环.
继续等待 read 中读取fifo数据,当后台的10个子进程后,按次序排队往fifo输入空行,这样fifo中又有了数据,for语句继续执行.
Tags: linux线程任务 shell多线程
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
 - PHP新手上路(一)(7)
 - 惹恼程序员的十件事(5)
 - PHP邮件发送例子,已测试成功(5)
 - 致初学者:PHP比ASP优秀的七个理由(4)
 - PHP会被淘汰吗?(4)
 - PHP新手上路(四)(4)
 - 如何去学习PHP?(2)
 - 简单入门级php分页代码(2)
 - php中邮箱email 电话等格式的验证(2)
 
