Shell并发控制:GNU parallel 跟bash原生命令的区别

在写并发启动viewer的shell脚本时,有这样一个业务场景:

每个master每秒最多连5个viewer,这样的话就导致在并发启动时,一个channel最多同时启动5个viewer,如果同时启动6个viewer,那么最后启动的那个viewer就会拉流失败。

所以对应的启动列表应该是这样:包含两列,分别是channel和index,例如,

列1 列2 备注
channel1 index1 代表viewer1
channel1 index2 代表viewer2
channel1 index3 代表viewer3
channel1 index4 代表viewer4
channel1 index5 代表viewer5
channel2 index1 代表viewer6
channel2 index2 代表viewer7

以此类推,这个列表可以是一千个,一万个甚至更多,用来并发。

那么在并发过程中如何实现多列输入、多参数替换呢?这就涉及到shell中的几种并发控制,这里介绍一下GNU parallelBash 原生命令(比如 &、wait、xargs -P),先说说它们的区别:

对比点 GNU parallel Bash 原生命令
语法简洁 非常简洁,几行代码搞定复杂任务 语法冗长,需手动管理 PIDs 或使用 xargs -P
并发控制 使用 -j N 控制并发数非常简单 xargs -P N 较为简单,但功能有限;手动控制难度较大
输入来源灵活 支持多个参数列、文件、stdin 等 需要手动处理传参(用 for 循环或数组)
错误处理 可内置 retry、timeout、log 自动聚合 需手动实现失败处理逻辑
可移植性 需要额外安装 所有类 Unix 系统自带 Bash
结果收集 内建 --results、–joblog 等日志功能 需额外代码实现结果/日志收集

举个例子,比如说想要实现:同时运行最多 3 个任务,总共执行 10 次 sleep 1

1、GNU parallel 命令:

seq 10 | parallel -j 3 'echo Starting job {}; sleep 1; echo Done job {}'

2、Bash + xargs -P 命令:

seq 10 | xargs -n1 -P 3 -I {} bash -c 'echo Start {}; sleep 1; echo Done {}'

(1)-P 3 的意思是:最多并发执行 3 个任务。
(2)一次处理一个参数 {},但最多 3 个并发。
(3)-n1,一次处理 1 个参数,无法直接处理多列(比如同时处理 sn 和 channel),要传多个参数需要手动拼接、再在子脚本中拆分,不方便 。

看到这里,就可以知道要实现最上面提到的业务场景应该用哪种方式控制并发了,是的,parallel。

parallel 支持 多列输入、多参数替换,例如:

cat sn_channel_list.txt | parallel -j 3 'echo SN: {1}, Channel: {2}'

1、文件中每行有两个字段(比如 SN 和 Channel);
2、{1} 代表第一个字段,{2} 代表第二个字段;
3、parallel 自动拆解参数并填入命令中,很方便。

【总结】
1、xargs 不支持参数列选择 {1}, {2},也不支持数组参数,扩展性差。
2、parallel 支持多字段、多参数替换,更适合当前业务场景的需要。

你可能感兴趣的:(AWS,WebRTC,gnu,bash,linux,aws,webrtc,服务器,运维)