Bash脚本如何并行执行3万条IP的curl请求以缩短整体执行时间
批量IP连通性检测脚本并发优化方案
你当前的串行执行脚本每次都要等上一个curl请求返回或超时才会处理下一个IP,3万条记录跑下来耗时会非常久,改成并发处理可以大幅缩短整体执行时间,常见的实现方案如下:
方案1:用xargs实现并发(无需额外安装工具)
大部分Linux发行版自带的xargs支持-P参数指定并发执行的进程数,是成本最低的优化方案:
# 先导出你的原有变量,保证子进程可以读取 export ok="你原有脚本里的匹配规则" export outfile="./输出日志路径.log" export faillog="./失败IP记录.log" # 把检测逻辑封装为可导出的函数 check_single_ip() { local ip="$1" local resp=$(curl -i -m1 "http://${ip}" 2>&1) echo "$resp" | grep -Eo "$ok" > /dev/null if [ $? -ne 0 ]; then echo -e "Command: curl -i -m1 http://${ip} 2>&1" >> "${outfile}" echo -e "failed: ${ip}:\n\n \"${resp}\"\n\n" >> "${outfile}" echo "${ip}" >> "${faillog}" fi } export -f check_single_ip # 并发数设为20,可根据你的网络带宽调整,不要过高以免造成网络拥塞 cat "${你的IP文件路径}" | xargs -P 20 -I {} bash -c 'check_single_ip {}'
方案2:Bash内置后台进程控制
如果不想依赖xargs,也可以自己用bash的后台进程+阈值控制实现并发:
# 定义最大并发数 MAX_CONCURRENT=20 # 临时文件存储后台进程ID,用于进程数控制 pids_tmp=$(mktemp) while IFS= read -r ip || [[ -n "$ip" ]]; do # 把检测逻辑放到后台执行 ( resp=$(curl -i -m1 "http://${ip}" 2>&1) echo "$resp" | grep -Eo "$ok" > /dev/null if [ $? -ne 0 ]; then echo -e "Command: curl -i -m1 http://${ip} 2>&1" >> "${outfile}" echo -e "failed: ${ip}:\n\n \"${resp}\"\n\n" >> "${outfile}" echo "${ip}" >> "${faillog}" fi ) & echo $! >> "$pids_tmp" # 进程数达到阈值后等待当前批次执行完成再继续 if [ $(wc -l < "$pids_tmp") -ge $MAX_CONCURRENT ]; then wait $(cat "$pids_tmp") rm "$pids_tmp" pids_tmp=$(mktemp) fi done < "${你的IP文件路径}" # 等待最后一批剩余的后台进程执行完成 wait rm -f "$pids_tmp"
注意事项
- 并发数不要设置过高,普通家用网络建议设为2050,服务器带宽充足的情况下可以调整到100200,过高会导致网络拥塞、请求超时率升高,还可能触发目标站点的限流规则。
- 如果运行中出现日志内容错乱的问题,可以在写日志的操作前加文件锁,比如把
echo "${ip}" >> "${faillog}"改成echo "${ip}" | flock "${faillog}" tee -a "${faillog}" >/dev/null即可。 - 对性能要求更高的场景可以直接用curl原生的并行请求能力,无需创建多个子进程,性能消耗更低。
内容的提问来源于stack exchange,提问作者Marco Ferrara
相关产品推荐
相关产品推荐

