使用GNU Parallel运行Bash循环Curl脚本的技术问询
用GNU Parallel处理动态更新的IP列表(10并行任务)
看起来你已经找对了工具——GNU Parallel确实是处理这类并行任务的绝佳选择,尤其是面对动态更新的任务列表时。下面我会给你一套实用的解决方案,解决"安全获取IP、并行执行Curl、避免重复处理"这几个核心问题:
核心思路
因为你的IP列表会被其他脚本持续更新,而且多个并行进程同时操作同一个文件会出现竞争问题(比如两个进程读取到同一个IP),所以我们需要原子性的文件操作来确保每次只有一个进程能获取并移除IP,再配合Parallel启动10个常驻worker来循环处理任务。
完整脚本实现
#!/bin/bash # 定义你的IP列表文件路径,替换成实际路径 IP_LIST_FILE="/tmp/dynamic_ip_list.txt" # 安全获取并移除列表中的下一个IP(原子操作) get_next_ip() { # 给文件加排他锁,超时5秒避免无限等待 flock -w 5 "$IP_LIST_FILE" || return 1 # 读取第一行IP read -r ip < "$IP_LIST_FILE" # 如果没有IP了,释放锁并返回失败 if [ -z "$ip" ]; then flock -u "$IP_LIST_FILE" return 1 fi # 删除第一行(保留剩余内容) sed -i '1d' "$IP_LIST_FILE" # 释放锁 flock -u "$IP_LIST_FILE" echo "$ip" } # 单个worker的逻辑:循环获取IP并执行Curl worker() { while true; do # 获取下一个IP ip=$(get_next_ip) # 如果暂时没有IP,等待1秒再检查(因为列表会被其他脚本更新) if [ -z "$ip" ]; then sleep 1 continue fi # 执行你的Curl命令,替换成实际业务逻辑 echo "[Worker $$] Processing IP: $ip" curl -s -o /dev/null -w "Status: %{http_code} for $ip\n" "http://$ip" # 可选:处理Curl执行失败的情况 if [ $? -ne 0 ]; then echo "[Worker $$] Failed to process $ip" >&2 fi done } # 导出变量让Parallel的worker进程能访问 export IP_LIST_FILE # 启动10个并行worker parallel -j 10 worker ::: {1..10}
关键细节解释
- 文件锁(flock):这是避免并发冲突的核心,确保同一时间只有一个worker能读取和修改IP列表,彻底解决多个进程抢同一IP的问题。
- 原子读取删除:通过
read读取第一行,再用sed -i '1d'删除该行,整个过程在锁的保护下完成,保证操作的原子性。 - 常驻worker:每个worker会持续循环,当列表为空时会短暂休眠后再次检查,这样就能自动处理后续新增的IP。
- 并行控制:
-j 10指定启动10个并行worker,刚好符合你的需求。
注意事项
- 如果你的IP列表非常大,
sed -i的效率可能会降低,这时可以考虑用临时文件来替换(比如把除第一行外的内容写入临时文件,再替换原文件)。 - 可以根据实际情况调整
flock的超时时间(-w 5),如果不需要超时可以去掉这个参数。 - 若需要优雅停止所有worker,可以直接按
Ctrl+C终止脚本,或者用pkill -f parallel来结束进程。
内容的提问来源于stack exchange,提问作者Nikolas K
相关产品推荐
相关产品推荐

