如何在Bash脚本中实现多主机并行Rsync文件传输
使用GNU Parallel实现(推荐)
GNU Parallel对并行任务的控制更灵活,对错误处理、日志输出的支持也更完善,适配你原有逻辑的代码如下:
# 全并行执行所有主机的rsync任务 parallel -j 0 rsync -rv --checksum folder/ -e "ssh -i rsa_key -o StrictHostKeyChecking=no" user@{}:/var/test/folder --delete ::: "${listofhosts[@]}"
参数说明:
-j用来指定并行任务数,设为0表示同时运行所有任务,如果你需要限制带宽占用避免占满出口链路,可以改成具体数值,比如-j 8就是最多同时给8台主机传文件{}是主机名占位符,会被后面:::传入的listofhosts数组中的每一个元素替换- 如果你需要保留原有脚本中「任意一台主机传输失败就立刻终止所有操作」的逻辑,添加
--halt now,fail=1参数即可:
parallel --halt now,fail=1 -j 0 rsync -rv --checksum folder/ -e "ssh -i rsa_key -o StrictHostKeyChecking=no" user@{}:/var/test/folder --delete ::: "${listofhosts[@]}"
使用xargs实现(系统原生,无需额外安装软件)
如果你的环境不允许安装额外软件,用系统自带的xargs也可以实现并行,代码如下:
printf "%s\n" "${listofhosts[@]}" | xargs -I {} -P 0 rsync -rv --checksum folder/ -e "ssh -i rsa_key -o StrictHostKeyChecking=no" user@{}:/var/test/folder --delete
参数说明:
-I {}指定输入的每一行内容替换命令中的{}占位符-P用来指定并行任务数,设为0表示不限制并行数,同样可以修改为具体数值限制并发- xargs原生不支持「单任务失败就终止所有任务」的逻辑,如果需要实现该逻辑,可以用临时文件记录错误状态,示例如下:
err_flag=$(mktemp) printf "%s\n" "${listofhosts[@]}" | xargs -I {} -P 0 bash -c 'rsync -rv --checksum folder/ -e "ssh -i rsa_key -o StrictHostKeyChecking=no" user@{}:/var/test/folder --delete || echo fail > "$0"' "$err_flag" if grep -qs "fail" "$err_flag"; then rm -f "$err_flag" exit 1 fi rm -f "$err_flag"
注意事项
- 两种方案的rsync参数都和你原有脚本完全一致,不需要修改原有同步规则
- 如果你的主机数量超过20台,建议不要用全并行,根据你的带宽大小设置合理的并发数,避免本地带宽被占满或者触发远端SSH服务的连接限制
内容的提问来源于stack exchange,提问作者antiks
相关产品推荐
相关产品推荐

