博客自动监控与IP优选脚本教程
一、背景介绍
在维护个人博客时,我们经常会遇到以下问题:
Cloudflare IP被限制访问
服务器IP被屏蔽
CDN节点故障导致访问缓慢或无法访问
网络线路波动影响用户体验
为了解决这些问题,我编写了一个自动化监控和IP优选脚本,当博客无法访问时自动执行IP优选操作,确保博客始终可访问。
此教程配合saas来实现,其中RECORD_NAME为回源域名
二、脚本功能
2.1 核心功能
自动监控 :每5分钟检测博客是否可访问
智能IP优选 :检测到异常时自动执行IP优选脚本
Cloudflare管理 :自动检查和修正CNAME记录
多重策略 :执行2次IP优选后自动切换备用CNAME
详细日志 :记录所有操作和诊断信息
2.2 工作流程
博客监控 → 检测到异常 → 第1次执行IP优选 → 等待5分钟
↓
再次检测 → 仍然异常 → 第2次执行IP优选 → 等待5分钟
↓
再次检测 → 仍然异常 → 切换CNAME记录 → 等待DNS生效
↓
再次检测 → 恢复正常或记录错误
三、环境准备
3.1 系统要求
OpenWrt / Linux 系统
安装 curl、nslookup、nc 等工具
Cloudflare API访问权限
3.2 获取Cloudflare API信息
登录Cloudflare控制台
获取API Key :
点击右上角头像 → "我的个人资料"
选择"API令牌" → "创建令牌"
选择"编辑区域DNS"模板
生成令牌并保存
获取Zone ID :
3.3 准备IP优选脚本
创建 /root/cu.sh 作为IP优选脚本:
#!/bin/bash
echo "开始IP优选..."
四、脚本详解
4.1 完整脚本代码
#!/bin/sh
URL="https://yourblog.com"
TIMEOUT=30
MAX_RETRY=2
YX_SCRIPT="/root/cu.sh"
LOG_FILE="/var/log/blog_monitor.log"
LOCK_FILE="/tmp/blog_monitor.lock"
RETRY_COUNT_FILE="/tmp/cu_retry_count.txt"
CF_API_KEY="your_cloudflare_api_key"
CF_EMAIL="[email protected] "
ZONE_ID="your_zone_id"
RECORD_NAME="cname.example.com"
EXPECTED_TARGET="target1.example.com"
FALLBACK_TARGET="target2.example.com"
log () {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1 " >> "$LOG_FILE "
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1 "
}
reset_retry_count () {
echo "0" > "$RETRY_COUNT_FILE "
log "已重置IP优选次数计数"
}
get_retry_count () {
if [ -f "$RETRY_COUNT_FILE " ]; then
cat "$RETRY_COUNT_FILE "
else
echo "0"
fi
}
increment_retry_count () {
local current=$(get_retry_count)
local new=$((current + 1 ))
echo "$new " > "$RETRY_COUNT_FILE "
echo "$new "
}
get_current_cname () {
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID /dns_records?name=$RECORD_NAME &type=CNAME" \
-H "X-Auth-Email: $CF_EMAIL " \
-H "X-Auth-Key: $CF_API_KEY " \
-H "Content-Type: application/json" | grep -o '"content":"[^"]*"' | head -1 | cut -d'"' -f4
}
get_record_id () {
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID /dns_records?name=$RECORD_NAME &type=CNAME" \
-H "X-Auth-Email: $CF_EMAIL " \
-H "X-Auth-Key: $CF_API_KEY " \
-H "Content-Type: application/json" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4
}
update_cloudflare_cname () {
local target_value="$1 "
log "开始修改Cloudflare CNAME记录: $RECORD_NAME -> $target_value "
RECORD_ID=$(get_record_id)
if [ -z "$RECORD_ID " ]; then
log "错误: 无法获取 $RECORD_NAME 的记录ID"
return 1
fi
log "获取到记录ID: $RECORD_ID "
UPDATE_RESULT=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID /dns_records/$RECORD_ID " \
-H "X-Auth-Email: $CF_EMAIL " \
-H "X-Auth-Key: $CF_API_KEY " \
-H "Content-Type: application/json" \
--data "{\"type\":\"CNAME\",\"name\":\"$RECORD_NAME \",\"content\":\"$target_value \",\"ttl\":120,\"proxied\":false}" )
if echo "$UPDATE_RESULT " | grep -q '"success":true' ; then
log "Cloudflare CNAME记录更新成功: $RECORD_NAME -> $target_value "
return 0
else
log "Cloudflare CNAME记录更新失败: $UPDATE_RESULT "
return 1
fi
}
ensure_correct_cname () {
log "检查 $RECORD_NAME 的CNAME记录..."
CURRENT_CNAME=$(get_current_cname)
if [ -z "$CURRENT_CNAME " ]; then
log "警告: 无法获取当前CNAME记录,尝试创建新的记录"
CREATE_RESULT=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID /dns_records" \
-H "X-Auth-Email: $CF_EMAIL " \
-H "X-Auth-Key: $CF_API_KEY " \
-H "Content-Type: application/json" \
--data "{\"type\":\"CNAME\",\"name\":\"$RECORD_NAME \",\"content\":\"$EXPECTED_TARGET \",\"ttl\":120,\"proxied\":false}" )
if echo "$CREATE_RESULT " | grep -q '"success":true' ; then
log "成功创建CNAME记录: $RECORD_NAME -> $EXPECTED_TARGET "
return 0
else
log "创建CNAME记录失败: $CREATE_RESULT "
return 1
fi
elif [ "$CURRENT_CNAME " != "$EXPECTED_TARGET " ]; then
log "当前CNAME值: $CURRENT_CNAME (不符合预期)"
log "将更新为: $EXPECTED_TARGET "
update_cloudflare_cname "$EXPECTED_TARGET "
return $?
else
log "CNAME记录正确: $RECORD_NAME -> $EXPECTED_TARGET ✓"
return 0
fi
}
get_current_resolve () {
nslookup "$RECORD_NAME " 2>/dev/null | grep -A1 "Name:" | tail -n1 | awk '{print $2}'
}
check_access () {
for i in $(seq 1 $MAX_RETRY ); do
RESPONSE=$(curl -sLk -w "\n%{http_code}" --connect-timeout $TIMEOUT "$URL " 2>&1)
HTTP_CODE=$(echo "$RESPONSE " | tail -n1)
BODY=$(echo "$RESPONSE " | head -n -1)
if echo "$BODY " | grep -q "Cloudflare\|Error 1034\|Edge IP Restricted" ; then
log "检测到Cloudflare错误: Edge IP Restricted"
return 2
fi
if [ "$HTTP_CODE " -ge 200 ] && [ "$HTTP_CODE " -lt 400 ]; then
return 0
elif [ "$HTTP_CODE " = "403" ] && echo "$BODY " | grep -q "Cloudflare" ; then
log "Cloudflare阻止访问 (HTTP 403)"
return 3
fi
log "第${i} 次检测失败,HTTP状态码: $HTTP_CODE "
sleep 3
done
return 1
}
run_optimize_script () {
ensure_correct_cname
if [ -x "$YX_SCRIPT " ]; then
log "执行IP优选脚本: $YX_SCRIPT "
"$YX_SCRIPT " >> "$LOG_FILE " 2>&1
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
log "IP优选脚本执行成功"
return 0
else
log "IP优选脚本执行失败,退出码: $EXIT_CODE "
return 1
fi
else
log "错误: IP优选脚本 $YX_SCRIPT 不存在或不可执行"
return 1
fi
}
diagnose_network () {
log "========== 开始网络诊断 =========="
CURRENT_IP=$(get_current_resolve)
log "当前 $RECORD_NAME 解析到: $CURRENT_IP "
SITE_IP=$(nslookup ${URL#https://} 2>/dev/null | grep -A1 "Name:" | tail -n1 | awk '{print $2}' )
log "${URL#https://} 解析到: $SITE_IP "
CURRENT_CNAME=$(get_current_cname)
log "Cloudflare中 $RECORD_NAME 的CNAME值: $CURRENT_CNAME "
if [ -n "$CURRENT_IP " ]; then
PING_RESULT=$(ping -c 3 -W 2 "$CURRENT_IP " 2>&1)
if echo "$PING_RESULT " | grep -q "0% packet loss" ; then
log "Ping $CURRENT_IP 成功"
else
log "Ping $CURRENT_IP 失败"
fi
fi
if [ -n "$CURRENT_IP " ]; then
PORT_CHECK=$(nc -zv -w 3 "$CURRENT_IP " 443 2>&1)
if echo "$PORT_CHECK " | grep -q "succeeded\|Connected" ; then
log "端口443连接成功"
else
log "端口443连接失败"
fi
fi
log "========== 网络诊断结束 =========="
}
if [ -f "$LOCK_FILE " ] && [ $(find "$LOCK_FILE " -mmin -5 2>/dev/null) ]; then
log "IP优选脚本已在执行中(5分钟内),跳过本次检测"
exit 0
fi
check_access
RETURN_CODE=$?
case $RETURN_CODE in
0)
log "博客可正常访问 ✓"
reset_retry_count
;;
2|3)
touch "$LOCK_FILE "
RETRY_COUNT=$(increment_retry_count)
log "检测到Cloudflare错误 (当前已执行第${RETRY_COUNT} 次IP优选)"
if [ "$RETRY_COUNT " -ge 2 ]; then
log "【重要】已执行IP优选两次,网站仍无法访问"
diagnose_network
log "确保CNAME记录为 $EXPECTED_TARGET "
ensure_correct_cname
sleep 10
log "检查CNAME修正后网站是否恢复..."
check_access
if [ $? -eq 0 ]; then
log "修正CNAME后网站恢复访问 ✓"
reset_retry_count
else
log "修正CNAME后网站仍无法访问,尝试备用方案: $FALLBACK_TARGET "
update_cloudflare_cname "$FALLBACK_TARGET "
reset_retry_count
sleep 30
NEW_IP=$(get_current_resolve)
log "DNS更新后,$RECORD_NAME 解析到: $NEW_IP "
check_access
if [ $? -eq 0 ]; then
log "切换到备用CNAME后网站恢复访问 ✓"
else
log "所有IP优选方案均失败,请手动检查配置"
diagnose_network
fi
fi
else
log "第一次执行IP优选,先确保CNAME正确"
ensure_correct_cname
run_optimize_script
fi
rm -f "$LOCK_FILE "
;;
*)
touch "$LOCK_FILE "
RETRY_COUNT=$(increment_retry_count)
log "博客无法访问 (当前已执行第${RETRY_COUNT} 次IP优选)"
if [ "$RETRY_COUNT " -ge 2 ]; then
diagnose_network
ensure_correct_cname
sleep 10
check_access
if [ $? -eq 0 ]; then
log "修正CNAME后网站恢复访问 ✓"
reset_retry_count
else
log "修正CNAME后网站仍无法访问,尝试备用方案: $FALLBACK_TARGET "
update_cloudflare_cname "$FALLBACK_TARGET "
reset_retry_count
sleep 30
check_access
if [ $? -eq 0 ]; then
log "切换到备用CNAME后网站恢复访问 ✓"
else
log "所有IP优选方案均失败,请手动检查"
diagnose_network
fi
fi
else
ensure_correct_cname
run_optimize_script
fi
rm -f "$LOCK_FILE "
;;
esac
4.2 配置说明
配置项
说明
示例
URL
监控的网站地址
https://yourblog.com
TIMEOUT
请求超时时间
30秒
MAX_RETRY
检测失败重试次数
2次
YX_SCRIPT
IP优选脚本路径
/root/cu.sh
CF_API_KEY
Cloudflare API密钥
从Cloudflare获取
CF_EMAIL
Cloudflare账户邮箱
[email protected]
ZONE_ID
域名区域ID
从Cloudflare获取
RECORD_NAME
要管理的DNS记录
cname.example.com
EXPECTED_TARGET
期望的CNAME值
target1.example.com
FALLBACK_TARGET
备用CNAME值
target2.example.com
五、部署步骤
5.1 上传脚本
vi /root/blog_monitor.sh
chmod +x /root/blog_monitor.sh
vi /root/cu.sh
chmod +x /root/cu.sh
5.2 测试运行
/root/blog_monitor.sh
tail -f /var/log/blog_monitor.log
5.3 设置定时任务
使用crontab设置每5分钟执行一次:
crontab -e
*/5 * * * * /root/blog_monitor.sh
crontab -l
5.4 OpenWrt特定设置
如果使用OpenWrt,可以使用其内置的定时任务:
vi /etc/crontabs/root
*/5 * * * * /root/blog_monitor.sh
/etc/init.d/cron restart
六、监控与维护
6.1 查看日志
tail -f /var/log/blog_monitor.log
tail -100 /var/log/blog_monitor.log
grep "IP优选" /var/log/blog_monitor.log
grep "错误" /var/log/blog_monitor.log
6.2 手动干预
cat /tmp/cu_retry_count.txt
echo "0" > /tmp/cu_retry_count.txt
/root/blog_monitor.sh
/root/cu.sh
6.3 常见问题处理
问题1:脚本无法执行
ls -l /root/blog_monitor.sh
chmod +x /root/blog_monitor.sh
问题2:Cloudflare API认证失败
curl -X GET "https://api.cloudflare.com/client/v4/zones" \
-H "X-Auth-Email: [email protected] " \
-H "X-Auth-Key: your_api_key" \
-H "Content-Type: application/json"
问题3:IP优选脚本执行失败
ls -l /root/cu.sh
/root/cu.sh
/root/cu.sh 2>&1
问题4:DNS解析延迟
/etc/init.d/dnsmasq restart
/etc/init.d/dnsmasq reload
nslookup cname.example.com
七、IP优选脚本示例
7.1 基础IP优选脚本
#!/bin/bash
IPS=(
"104.16.0.0"
"104.17.0.0"
"104.18.0.0"
"104.19.0.0"
"104.20.0.0"
)
test_latency () {
local ip=$1
local latency=$(ping -c 3 -W 2 "$ip " 2>/dev/null | grep "avg" | awk -F'/' '{print $5}' )
echo "$latency "
}
best_ip=""
best_latency=9999
for ip in "${IPS[@]} " ; do
latency=$(test_latency "$ip " )
if [ -n "$latency " ] && [ $(echo "$latency < $best_latency " | bc) -eq 1 ]; then
best_latency=$latency
best_ip=$ip
fi
done
if [ -n "$best_ip " ]; then
echo "优选IP: $best_ip , 延迟: ${best_latency} ms"
else
echo "未找到可用IP"
exit 1
fi
7.2 高级IP优选脚本
#!/bin/bash
get_ip_pool () {
curl -s "https://api.example.com/cf-ips" | jq -r '.ips[]' 2>/dev/null || echo "104.16.0.0 104.17.0.0"
}
test_response () {
local ip=$1
curl -s -o /dev/null -w "%{time_total}" --connect-timeout 3 "http://$ip " 2>/dev/null
}
score_ip () {
local ip=$1
local latency=$(test_response "$ip " )
local loss=$(ping -c 10 -W 2 "$ip " 2>/dev/null | grep -o "[0-9]\+% packet loss" | grep -o "[0-9]\+" )
loss=${loss:-100}
if [ -n "$latency " ]; then
score=$(echo "scale=2; 100 - $latency *10 - $loss /10" | bc 2>/dev/null || echo "0" )
echo "$score "
else
echo "0"
fi
}
echo "开始IP优选..."
八、性能优化建议
8.1 监控频率优化
根据实际情况调整监控频率:
稳定期:每10分钟检测一次
不稳定期:每3分钟检测一次
*/10 * * * * /root/blog_monitor.sh
*/3 * * * * /root/blog_monitor.sh
8.2 IP池优化
定期更新IP池数据
使用CDN服务商提供的官方IP列表
加入地域性IP分组
8.3 日志管理
cat > /etc/logrotate.d/blog_monitor << EOF
/var/log/blog_monitor.log {
weekly
rotate 4
compress
missingok
notifempty
}
EOF
九、注意事项
API密钥安全 :不要将包含API密钥的脚本提交到公开仓库
频率控制 :IP优选频率不要太频繁,避免被误认为攻击
备份配置 :定期备份Cloudflare DNS配置
测试环境 :先在测试环境验证脚本功能
监控告警 :建议配置告警通知,及时了解异常情况
IP池更新 :定期更新IP优选池,保证有效性
十、总结
通过这个自动化监控和IP优选脚本,我们可以:
实时监控博客可用性
自动执行IP优选操作
智能管理DNS记录
详细记录所有操作
这套方案大大减少了手动运维的工作量,让博客更加稳定可靠。IP优选策略能够有效应对网络波动和IP限制问题,确保访客始终能够访问到最优的节点。
十一、参考资源
Cloudflare API文档
OpenWrt crontab文档
Shell脚本编程指南
Cloudflare优选IP工具
更新日期 :2026年8月21日
脚本版本 :v2.0
适用环境 :OpenWrt/Linux
标签 :#博客监控 #IP优选 #Cloudflare #自动化运维