shell脚本内的并发执行

目录

  1. 1. 顺序执行
  2. 2. 并发执行

之前有一个每周数据统计的工作,需要每周的某一天定时从多台服务器上拉取日志进行汇总生成报表。

顺序执行

最初的思路是先做一个循环,遍历每台机器并在上面执行相应的数据处理脚本,然后将处理好的数据拉取到汇总的机器上,这样逐台进行,最后进行汇总处理,写出来的脚本是类似这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
array=( \
"10.144.1.1" \
"10.144.1.2" \
"10.144.1.3" \
"10.144.1.4" \
)

for i in ${array[@]}
do
ssh $i "sh $log_dir/run.sh"
scp $i:$log_dir/log $work_dir/$i/
done

cat $work_dir/*/log | sort | uniq > $work_dir/log

这样写的执行时间大约是每台机器时间*台数+汇总时间,虽然不算快,但是凌晨一般也能执行完成。

并发执行

后来到了国庆假期期间,服务流量骤增,再加上业务改版等一系列原因,导致数据量突然增大,执行时间翻了几倍,任务大概要到下午才能完成,这样一来就会耽误白天的工作。

因为机器数量不少,分机器统计也是主要的时间消耗,因此想到既然几台机器各自的统计互不影响,可以让它们同时进行汇总工作。于是上网找了一下改进方法,改完了大致是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
array=( \
"10.144.1.1" \
"10.144.1.2" \
"10.144.1.3" \
"10.144.1.4" \
)

for i in ${array[@]}
do {
ssh $i "sh $log_dir/run.sh"
scp $i:$log_dir/log $work_dir/$i/
}&
done
wait

cat $work_dir/*/log | sort | uniq > $work_dir/log

可以发现主要的改动就在for循环的内容用{}括起来并在末尾加个&,这样就可以实现多次循环一起执行了;另外在done后面加个wait是为了等待所有的循环都执行完成后再做后面的汇总工作,否则一旦有一个循环执行完成就会往下执行了。

这样的执行时间大约是每台机器时间+汇总时间,可以看出比最初快了很多。