如何使用parallel并行调用Bash函数批量检查30000个站点?
用GNU Parallel并行调用Bash函数批量检查站点
问题背景
我有一个用于检查30000多个站点的Bash脚本,定义了如下check_site函数:
check_site() { host=$1; ip=$2 resp=$(curl -i -m1 -H "Host: $host" http://$ip 2>&1) echo "$resp" | grep -Eo "$ok" > /dev/null if [ $? -ne 0 ]; then echo -e "Command: curl -i -m1 -H \"Host: $host\" http://$ip 2>&1" >> "${outlog}" echo -e "Block failed: $host:\n\"$resp\"\n\n" >> "${outlog}" httpresponse=$(echo "$resp" | grep HTTP/1.1) echo "$host $ip $httpresponse" >> "${faillog}" fi }
目前我通过check_site $host $ip的方式串行调用该函数,请问是否可以使用parallel并行调用此函数并传递$host和$ip参数?
解决方案
完全可以用GNU Parallel实现并行调用,以下是具体步骤和注意事项:
1. 导出函数和依赖变量
Parallel会启动子进程执行任务,需要先把自定义函数和函数中用到的变量导出到子进程环境:
# 导出check_site函数 export -f check_site # 导出函数依赖的变量(根据你的脚本实际情况调整) export ok outlog faillog
2. 选择合适的并行调用方式
根据你存储host和ip的方式,选对应的调用方法:
方式一:从文件读取配对的host和ip
如果你的host和ip已经按每行两个字段的格式存在文件(比如hosts_ips.txt)中:
# 每行对应一个host和ip,直接用-a参数指定文件 parallel -a hosts_ips.txt check_site
方式二:从数组中配对调用
如果你的host和ip分别存在两个数组hosts和ips中,用:::+保证参数一对一配对:
parallel check_site ::: "${hosts[@]}" :::+ "${ips[@]}"
方式三:通过管道传递参数
如果是通过其他命令输出获取host和ip(每行两个字段),可以用管道配合-N2指定每次取2个参数:
# 示例:假设从某个命令获取host和ip列表 generate_host_ip_list | parallel -N2 check_site
3. 控制并行进程数
默认Parallel会启动和CPU核心数相同的进程,对于30000+站点,建议根据服务器资源调整并发数,比如用-j参数指定同时运行50个进程:
parallel -j 50 -a hosts_ips.txt check_site
4. 避免日志写入冲突
高并发下多个进程同时写入日志文件可能导致内容交错,可通过flock锁定日志文件解决,修改函数中的日志写入部分:
# 修改outlog写入逻辑,加文件锁 echo -e "Command: curl -i -m1 -H \"Host: $host\" http://$ip 2>&1" | flock -x "${outlog}" -c 'cat >> "$1"' -- "${outlog}" echo -e "Block failed: $host:\n\"$resp\"\n\n" | flock -x "${outlog}" -c 'cat >> "$1"' -- "${outlog}" # 修改faillog写入逻辑 echo "$host $ip $httpresponse" | flock -x "${faillog}" -c 'cat >> "$1"' -- "${faillog}"
内容的提问来源于stack exchange,提问作者Marco Ferrara
相关产品推荐
相关产品推荐

