首页 > 系统 > Linux > 正文

linux中shell模拟多线程执行任务详解

2024-08-27 23:59:15
字体:
来源:转载
供稿:网友

多线程是对于linux系统来讲是小菜了,下面小编为各位整理一篇linux中shell模拟多线程执行任务详解,希望文章可以帮助到各位。

shell本身是不能实现多线程的,但是可以通过启动子进程,并将子进程放入后台执行来模拟多线程,为了在提高脚本执行效率的同时又不明显增加负载的作用,还需要对同时放入后台的进程数做下限制,代码如下:

  1. #!/bin/bash 
  2. set -x  # 开启调试模式 
  3. #判断是否有参数 
  4. if [ $# != 1 ];then 
  5.     echo "您输入的参数有误" 
  6.     exit -1 
  7. fi 
  8. # 允许的最大进程数 
  9. MAX_THREAD_NUM=5 
  10. tmp_fifo_file=/tmp/$$.fifo # 以脚本运行的当前进程ID号作为文件名 
  11. mkfifo "$tmp_fifo_file"    # 新建一个随机fifo管道文件 
  12. exec 9<>"$tmp_fifo_file"   # 定义文件描述符9指向这个fifo管道文件 
  13. rm "$tmp_fifo_file" 
  14. # 预先写入指定数量的换行符到fifo管道文件中,一个换行符代表一个进程 
  15. for((i=0;i<$MAX_THREAD_NUM;i++));do 
  16.      echo  
  17. done >&9 
  18. # 循环读出url并判断状态码 
  19. while read line 
  20. do 
  21.     # 进程控制 
  22.     read -u 9 # 从文件描述符9中读取行,实际指向fifo管道 
  23.     { 
  24.         isok=`curl -I -L -m 60 -o /dev/null -s -w %{http_code} $line
  25.         if [ "$isok" = "200" ];then 
  26.             echo $line "OK" 
  27.         else 
  28.             echo $line $isok 
  29.         fi 
  30.         echo >&9 # ,当前进程结束,往fifo管道文件中写入一个空行 
  31.     }&  //Vevb.com 
  32. done < $1 wait echo '执行结束' exec 9>&- # 删除文件描述符9 
  33. exit 0 

脚本的任务是对一个url列表中的网址进行判断,判断这些网址是否可以继续访问,具体方法是,通过curl获取http的状态码来判断.

上面红色部分{}中的语句被放进子进程中在后台执行,当fifo中5个空行读完后,循环继续等待 read 中读取fifo数据,当后台的子进程完成任务后,排队往fifo输入空行,这样fifo中又有了数据,循环继续执行.

下面看看shell执行的结果,代码如下:

  1. # bash scanUrl.sh url.txt  
  2. + '[' 1 '!=' 1 ']' 
  3. + MAX_THREAD_NUM=5 
  4. + tmp_fifo_file=/tmp/Vevb.com  
  5. + mkfifo /tmp/Vevb.com  
  6. + exec 
  7. + rm /tmp/Vevb.com  
  8. + (( i=0 )) 
  9. + (( i<5 )) 
  10. + echo 
  11. + (( i++ )) 
  12. + (( i<5 )) 
  13. + echo 
  14. + (( i++ )) 
  15. + (( i<5 )) 
  16. + echo 
  17. + (( i++ )) 
  18. + (( i<5 )) 
  19. + echo 
  20. + (( i++ )) 
  21. + (( i<5 )) 
  22. + echo 
  23. + (( i++ )) 
  24. + (( i<5 )) 
  25. + read line 
  26. + read -u 9 
  27. ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com / 
  28. + read line 
  29. + read -u 9 
  30. ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com / 
  31. + read line 
  32. + read -u 9 
  33. ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com / 
  34. + read line 
  35. + read -u 9 
  36. ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com / 
  37. + read line 
  38. + read -u 9 
  39. ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com / 
  40. + read line 
  41. + read -u 9      # fifo文件中的5个空行读完了,等待其它子进程写入fifo 
  42. + isok=200 
  43. + '[' 200 = 200 ']' 
  44. + echo http://Vevb.com / OK 
  45. http://Vevb.com / OK 
  46. + echo          # 这个子进程完成任务,写入fifo一个空行,启动一个子进程 
  47. ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com / 
  48. + read line 
  49. + read -u 9 
  50. + isok=200 
  51. + '[' 200 = 200 ']' 
  52. + echo http://50vip.com/ OK 
  53. http://50vip.com/ OK 
  54. + echo 
  55. ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com /info/ 
  56. + read line 
  57. + read -u 9 
  58. + isok=200 
  59. + '[' 200 = 200 ']' 
  60. + echo http://361a.net/ OK 
  61. http://361a.net/ OK 
  62. + echo 
  63. ++ curl -I -L -m 60 -o /dev/null -s -w '%{http_code}' http://Vevb.com / 
  64. + read line 
  65. + wait         # 输入文件中的url都已经处理完成或在子进程中处理,等待所有子进程结束 
  66. + isok=200 
  67. + '[' 200 = 200 ']' 
  68. + echo http://Vevb.com / OK 
  69. http://Vevb.com / OK 
  70. + echo 
  71. + isok=000 
  72. + '[' 000 = 200 ']' 
  73. + echo http://5imovie.org/ 000 
  74. http://5imovie.org/ 000 
  75. + echo 
  76. + isok=200 
  77. + '[' 200 = 200 ']' 
  78. + echo http://Vevb.com / OK 
  79. http://52ixwebhosting.com/ OK 
  80. + echo 
  81. + isok=404 
  82. + '[' 404 = 200 ']' 
  83. + echo http://Vevb.com /info/ 404 
  84. http://Vevb.com /info/ 404 
  85. + echo 
  86. + isok=000 
  87. + '[' 000 = 200 ']' 
  88. + echo http://Vevb.com / 000 
  89. http://42.hcocoa.com/ 000 
  90. + echo 
  91. + echo $'346211247350241214347273223346235237' 
  92. 执行结束 
  93. + exec 
  94. + exit 0 

下面我们再来看个例子,代码如下:

  1. #!/bin/bash 
  2. function pinghost { 
  3. ping $1 -c 1 -w 10 |grep rtt|cut -d “/” -f6 
  4. tmp_fifofile=”/tmp/$.fifo”   # 脚本运行的当前进程ID号作为文件名 
  5. mkfifo $tmp_fifofile         # 新建一个随机fifo管道文件 
  6. exec 6<>$tmp_fifofile         # 定义文件描述符6指向这个fifo管道文件 
  7. rm $tmp_fifofile 
  8. thread=10 
  9. for ((i=0;i<$thread;i++));do   # for循环 往 fifo管道文件中写入10个空行 
  10. echo 
  11. done >&6 
  12. while read domain 
  13. do 
  14. read -u6                  # 从文件描述符6中读取行(实际指向fifo管道) 
  15. pinghost ${domain};      # 执行pinghost函数 
  16. echo >&6                      # 再次往fifo管道文件中写入一个空行。 
  17. }&                                  # 放到后台执行 
  18. done</home/miotour/ip.txt 
  19. wait                          #因为之前的进程都是后台执行,因此要有wait来等待所有的进程都执行完毕后才算整个脚本跑完。 
  20. exec 6>&-                #删除文件描述符6 
  21. exit 0 

说明:{} 这部分语句被放入后台作为一个子进程执行,这部分几乎是同时完成的,当fifo中10个空行读完后 while循环.

继续等待 read 中读取fifo数据,当后台的10个子进程后,按次序排队往fifo输入空行,这样fifo中又有了数据,for语句继续执行.

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表