如何在Bash的while read循环中实现并发连接执行任务?
问题描述
我有一个存储服务器列表的文件servers.txt,内容如下:
server1.me.com server2.me.com server3.me.com
我的Bash脚本如下:
#!/usr/bin/bash while read -r line do ssh -np2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$line" \ 'mkdir -pv /root/newimages/' rsync -Ptrave 'ssh -p2222' /root/*.tar "$line":/root/newimages/ ssh -np2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$line" \ 'find /root/newimages/ -name "*.tar" -exec docker load -i {} \;' done < servers.txt
当前脚本逐行执行任务,耗时较长。我希望同时最多处理5个服务器的任务,即同时建立SSH连接到多台服务器,请问该如何实现?
解决方案
方法1:Bash内置后台进程+wait控制并发
通过将单服务器任务放到后台执行,同时维护并发计数器,达到上限时等待任意一个后台进程结束再继续。修改后的脚本如下:
#!/usr/bin/bash MAX_PARALLEL=5 count=0 # 定义单服务器处理函数 process_server() { local server="$1" ssh -np2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$server" \ 'mkdir -pv /root/newimages/' rsync -Ptrave 'ssh -p2222' /root/*.tar "$server":/root/newimages/ ssh -np2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$server" \ 'find /root/newimages/ -name "*.tar" -exec docker load -i {} \;' } while read -r line do # 后台执行单服务器任务 process_server "$line" & ((count++)) # 并发数达上限时,等待一个进程完成 if (( count >= MAX_PARALLEL )); then wait -n ((count--)) fi done < servers.txt # 等待所有剩余后台进程执行完毕 wait
方法2:用xargs实现并发
xargs的-P参数可直接指定最大并发数,适合批量场景:
#!/usr/bin/bash process_server() { local server="$1" ssh -np2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$server" \ 'mkdir -pv /root/newimages/' rsync -Ptrave 'ssh -p2222' /root/*.tar "$server":/root/newimages/ ssh -np2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$server" \ 'find /root/newimages/ -name "*.tar" -exec docker load -i {} \;' } # 导出函数让xargs能调用 export -f process_server # 读取服务器列表,以5个并发执行任务 cat servers.txt | xargs -I {} -P5 bash -c 'process_server "$@"' _ {}
方法3:GNU Parallel(推荐)
GNU Parallel是专门的并行任务工具,语法简洁功能强,先通过包管理器安装(如apt install parallel或yum install parallel),然后使用:
#!/usr/bin/bash process_server() { local server="$1" ssh -np2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$server" \ 'mkdir -pv /root/newimages/' rsync -Ptrave 'ssh -p2222' /root/*.tar "$server":/root/newimages/ ssh -np2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no "$server" \ 'find /root/newimages/ -name "*.tar" -exec docker load -i {} \;' } # -j5指定最大5个并发,从servers.txt读取列表执行 parallel -j5 process_server :::: servers.txt
内容的提问来源于stack exchange,提问作者Saeed
相关产品推荐
相关产品推荐

