很多人都问我如何写shell脚本,如何实现同时给三台ftp服务器上传文件,如何同时检测三台服务器是否alive等,其实这就是想实现shell的并发。那么shell并发该如何实现呢?
可以看到执行此脚本大概用了20秒。那么使用shell并发该怎么写,很多人都会想到后台程序,类似如下:
这样就ok了,三个线程运行20个任务,7秒多点。
下面我就拿这个例子来讲:
每次任务都是输出字符“bingfa”,并停留一秒钟,共20次。
按照正常思维,脚本应该这样写:
- [root@station1 ~]# cat a.sh
- #!/bin/bash
- for((i=0;i<20;i++))
- do
- sleep 1
- echo "bingfa"
- done
- [root@station1 ~]# time bash a.sh
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- real 0m20.067s
- user 0m0.016s
- sys 0m0.031s
- [root@station1 ~]#
- [root@station1 ~]# cat b.sh
- #!/bin/bash
- for((i=0;i<20;i++))
- do
- {
- sleep 1
- echo "bingfa"
- }&
- done
- wait
- [root@station1 ~]# time bash b.sh
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- bingfa
- real 0m1.060s
- user 0m0.005s
- sys 0m0.057s
- [root@station1 ~]#
这样写只需花大概一秒钟,可以看到所有的任务几乎同时执行,如果任务量非常大,系统肯定承受不了,也会影响系统中其他程序的运行,这样就需要一个线程数量的控制。下面是我一开始写的代码(是有问题的):
- [root@station1 ~]# cat c.sh
- #!/bin/bash
- exec 6<>tmpfile
- echo "1\n1\n1" &>6
- for((i=0;i<20;i++))
- do
- read -u 6
- {
- sleep 1
- echo "$REPLY"
- echo "1" 1>&6
- }&
- done
- wait
- [root@station1 ~]# time bash c.sh
- 111
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- real 0m1.074s
- user 0m0.012s
- sys 0m0.031s
- [root@station1 ~]#
可以明显看出是有问题的,我本想控制线程个数为3,但是就算文件描述符6中为空,也会被读取空,然后跳过继续下面的执行,所以使用文件描述符打开一个文件是不行的,然后我就想着使用类似管道的文件来做,下面是我的代码:
- [root@station1 ~]# cat d.sh
- #!/bin/bash
- mkfifo fd2
- exec 9<>fd2
- echo -n -e "1\n1\n1\n" 1>&9
- for((i=0;i<20;i++))
- do
- read -u 9
- { #your process
- sleep 1
- echo "$REPLY"
- echo -ne "1\n" 1>&9
- } &
- done
- wait
- rm -f fd2
- [root@station1 ~]# time bash d.sh
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- real 0m7.075s
- user 0m0.018s
- sys 0m0.044s
- [root@station1 ~]#