Chinaunix首页 | 论坛 | 博客
  • 博客访问: 915331
  • 博文数量: 75
  • 博客积分: 1216
  • 博客等级: 少尉
  • 技术积分: 1998
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-11 16:20
个人简介

优秀是一种习惯

文章分类

全部博文(75)

文章存档

2014年(1)

2013年(29)

2012年(45)

分类: Python/Ruby

2013-01-12 10:39:50

    很多人都问我如何写shell脚本,如何实现同时给三台ftp服务器上传文件,如何同时检测三台服务器是否alive等,其实这就是想实现shell的并发。那么shell并发该如何实现呢?
    下面我就拿这个例子来讲:

    每次任务都是输出字符“bingfa”,并停留一秒钟,共20次。

    按照正常思维,脚本应该这样写:

  1. [root@station1 ~]# cat a.sh
  2. #!/bin/bash
  3. for((i=0;i<20;i++))
  4. do
  5. sleep 1
  6. echo "bingfa"
  7. done
  8. [root@station1 ~]# time bash a.sh
  9. bingfa
  10. bingfa
  11. bingfa
  12. bingfa
  13. bingfa
  14. bingfa
  15. bingfa
  16. bingfa
  17. bingfa
  18. bingfa
  19. bingfa
  20. bingfa
  21. bingfa
  22. bingfa
  23. bingfa
  24. bingfa
  25. bingfa
  26. bingfa
  27. bingfa
  28. bingfa
  29. real 0m20.067s
  30. user 0m0.016s
  31. sys 0m0.031s
  32. [root@station1 ~]#
可以看到执行此脚本大概用了20秒。那么使用shell并发该怎么写,很多人都会想到后台程序,类似如下:

  1. [root@station1 ~]# cat b.sh
  2. #!/bin/bash
  3. for((i=0;i<20;i++))
  4. do
  5. {
  6. sleep 1
  7. echo "bingfa"
  8. }&
  9. done
  10. wait
  11. [root@station1 ~]# time bash b.sh
  12. bingfa
  13. bingfa
  14. bingfa
  15. bingfa
  16. bingfa
  17. bingfa
  18. bingfa
  19. bingfa
  20. bingfa
  21. bingfa
  22. bingfa
  23. bingfa
  24. bingfa
  25. bingfa
  26. bingfa
  27. bingfa
  28. bingfa
  29. bingfa
  30. bingfa
  31. bingfa
  32. real 0m1.060s
  33. user 0m0.005s
  34. sys 0m0.057s
  35. [root@station1 ~]#

这样写只需花大概一秒钟,可以看到所有的任务几乎同时执行,如果任务量非常大,系统肯定承受不了,也会影响系统中其他程序的运行,这样就需要一个线程数量的控制。下面是我一开始写的代码(是有问题的):


  1. [root@station1 ~]# cat c.sh
  2. #!/bin/bash
  3. exec 6<>tmpfile
  4. echo "1\n1\n1" &>6
  5. for((i=0;i<20;i++))
  6. do
  7. read -u 6
  8. {
  9. sleep 1
  10. echo "$REPLY"
  11. echo "1" 1>&6
  12. }&
  13. done
  14. wait
  15. [root@station1 ~]# time bash c.sh
  16. 111
  17. 1
  18. 1
  19. 1
  20. 1
  21. 1
  22. 1
  23. 1
  24. 1
  25. 1
  26. 1
  27. 1
  28. 1
  29. 1
  30. 1
  31. 1
  32. 1
  33. 1
  34. 1
  35. 1
  36. real 0m1.074s
  37. user 0m0.012s
  38. sys 0m0.031s
  39. [root@station1 ~]#

可以明显看出是有问题的,我本想控制线程个数为3,但是就算文件描述符6中为空,也会被读取空,然后跳过继续下面的执行,所以使用文件描述符打开一个文件是不行的,然后我就想着使用类似管道的文件来做,下面是我的代码:


  1. [root@station1 ~]# cat d.sh
  2. #!/bin/bash
  3. mkfifo fd2
  4. exec 9<>fd2
  5. echo -n -e "1\n1\n1\n" 1>&9
  6. for((i=0;i<20;i++))
  7. do
  8. read -u 9
  9. { #your process
  10. sleep 1
  11. echo "$REPLY"
  12. echo -ne "1\n" 1>&9
  13. } &
  14. done
  15. wait
  16. rm -f fd2
  17. [root@station1 ~]# time bash d.sh
  18. 1
  19. 1
  20. 1
  21. 1
  22. 1
  23. 1
  24. 1
  25. 1
  26. 1
  27. 1
  28. 1
  29. 1
  30. 1
  31. 1
  32. 1
  33. 1
  34. 1
  35. 1
  36. 1
  37. 1
  38. real 0m7.075s
  39. user 0m0.018s
  40. sys 0m0.044s
  41. [root@station1 ~]#
这样就ok了,三个线程运行20个任务,7秒多点。

阅读(19165) | 评论(1) | 转发(5) |
给主人留下些什么吧!~~

wwmshe2013-01-15 16:55:57

文明上网,理性发言...