linux中shell模拟多线程执行任务详解
2019/10/10/17:45:51 阅读:1785 来源:谷歌SEO算法 标签:
SEO
多线程是对于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管道文件
- exec9<>"$tmp_fifo_file"#定义文件描述符9指向这个fifo管道文件
- rm"$tmp_fifo_file"
- #预先写入指定数量的换行符到fifo管道文件中,一个换行符代表一个进程
- for((i=0;i<$MAX_THREAD_NUM;i++));do
- echo
- done>&9
- #循环读出url并判断状态码
- whilereadline
- do
- {
- #进程控制
- read-u9#从文件描述符9中读取行,实际指向fifo管道
- {
- isok=`curl-I-L-m60-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<$1waitecho'执行结束'exec9>&-#删除文件描述符9
- exit0
脚本的任务是对一个url列表中的网址进行判断,判断这些网址是否可以继续访问,具体方法是,通过curl获取http的状态码来判断.
上面红色部分{}中的语句被放进子进程中在后台执行,当fifo中5个空行读完后,循环继续等待 read 中读取fifo数据,当后台的子进程完成任务后,排队往fifo输入空行,这样fifo中又有了数据,循环继续执行.
下面看看shell执行的结果,代码如下:
- #bashscanUrl.shurl.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))
- +readline
- +read-u9
- ++curl-I-L-m60-o/dev/null-s-w'%{http_code}'http://phpfensi.com /
- +readline
- +read-u9
- ++curl-I-L-m60-o/dev/null-s-w'%{http_code}'http://phpfensi.com /
- +readline
- +read-u9
- ++curl-I-L-m60-o/dev/null-s-w'%{http_code}'http://phpfensi.com /
- +readline
- +read-u9
- ++curl-I-L-m60-o/dev/null-s-w'%{http_code}'http://phpfensi.com /
- +readline
- +read-u9
- ++curl-I-L-m60-o/dev/null-s-w'%{http_code}'http://phpfensi.com /
- +readline
- +read-u9#fifo文件中的5个空行读完了,等待其它子进程写入fifo
- +isok=200
- +'['200=200']'
- +echohttp://phpfensi.com /OK
- http://phpfensi.com/OK
- +echo#这个子进程完成任务,写入fifo一个空行,启动一个子进程
- ++curl-I-L-m60-o/dev/null-s-w'%{http_code}'http://phpfensi.com /
- +readline
- +read-u9
- +isok=200
- +'['200=200']'
- +echohttp://50vip.com/OK
- http://50vip.com/OK
- +echo
- ++curl-I-L-m60-o/dev/null-s-w'%{http_code}'http://phpfensi.com /info/
- +readline
- +read-u9
- +isok=200
- +'['200=200']'
- +echohttp://361a.net/OK
- http://361a.net/OK
- +echo
- ++curl-I-L-m60-o/dev/null-s-w'%{http_code}'http://phpfensi.com /
- +readline
- +wait#输入文件中的url都已经处理完成或在子进程中处理,等待所有子进程结束
- +isok=200
- +'['200=200']'
- +echohttp://phpfensi.com /OK
- http://phpfensi.com /OK
- +echo
- +isok=000
- +'['000=200']'
- +echohttp://5imovie.org/000
- http://5imovie.org/000
- +echo
- +isok=200
- +'['200=200']'
- +echohttp://phpfensi.com /OK
- http://52ixwebhosting.com/OK
- +echo
- +isok=404
- +'['404=200']'
- +echohttp://phpfensi.com /info/404
- http://phpfensi.com /info/404
- +echo
- +isok=000
- +'['000=200']'
- +echohttp://phpfensi.com /000
- http://42.hcocoa.com/000
- +echo
- +echo$'346211247350241214347273223346235237'
- 执行结束
- +exec
- +exit0
下面我们再来看个例子,代码如下:
- #!/bin/bash
- functionpinghost{
- ping$1-c1-w10|greprtt|cut-d“/”-f6
- }
- tmp_fifofile=”/tmp/$.fifo”#脚本运行的当前进程ID号作为文件名
- mkfifo$tmp_fifofile#新建一个随机fifo管道文件
- exec6<>$tmp_fifofile#定义文件描述符6指向这个fifo管道文件
- rm$tmp_fifofile
- thread=10
- for((i=0;i<$thread;i++));do#for循环往fifo管道文件中写入10个空行
- echo
- done>&6
- whilereaddomain
- do
- read-u6#从文件描述符6中读取行(实际指向fifo管道)
- {
- pinghost${domain};#执行pinghost函数
- echo>&6#再次往fifo管道文件中写入一个空行。
- }&#放到后台执行
- done</home/miotour/ip.txt
- wait#因为之前的进程都是后台执行,因此要有wait来等待所有的进程都执行完毕后才算整个脚本跑完。
- exec6>&-#删除文件描述符6
- exit0
说明:{} 这部分语句被放入后台作为一个子进程执行,这部分几乎是同时完成的,当fifo中10个空行读完后 while循环.
继续等待 read 中读取fifo数据,当后台的10个子进程后,按次序排队往fifo输入空行,这样fifo中又有了数据,for语句继续执行.
热门评论