You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 13:50:07