shell脚本实现多进程并发


普通脚本执行

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env bash

for i in {1..255}
do
ip=118.25.100.$i
ping -c1 -W1 $ip &> /dev/null
if [ $? -eq 0 ]
then
echo "$ip is alive..."
fi
done

执行结果:

1
real	2m11.793s

执行时长约 2 分 12 秒,按顺序一个一个执行。


多进程并发执行

在循环块前后加大括号并放在后台执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env bash

for i in {1..255}
do
{
ip=118.25.100.$i
ping -c1 -W1 $ip &> /dev/null
if [ $? -eq 0 ]
then
echo "$ip is alive..."
fi
}&
done
wait
echo "all of finished..."

执行结果:

1
real	0m1.901s

效率提升了 60 多倍!


并发数量过大导致的问题

如果并发数量过大,系统可能无法处理:

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env bash

for i in {1..65535}
do
{
tcping 118.25.100.250 $i | grep open
}&
done
wait
echo "all of finished..."

执行结果:内存几乎被占满,负载达到 330+。


控制并发数量

使用命名管道控制并发数量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#!/usr/bin/env bash

fifo_file=/tmp/$$_fifofile
mkfifo $fifo_file
exec 54<> $fifo_file
rm -rf $fifo_file

# 控制并发数量为 10
for i in {1..10}
do
echo >&54
done

# 任务数量 65535
for i in {1..65535}
do
read -u 54
{
tcping -t1 118.25.100.250 $i
}&
echo >&54
done
wait
exec 54<&-
echo "all of finished..."

总结

方式 执行时间 特点
普通顺序执行 ~2分钟 稳定但慢
完全并发 ~2秒 快但资源占用高
控制并发数 可控 推荐使用

通过调整并发数量,可以在提高执行效率的同时不影响线上业务。