#!/bin/bash #完善授权信息之后的几个变量内容 #用法: bash cfddns.sh 二级域名 which jq >/dev/null 2>&1 || yum install jq -y >/dev/null 2>&1 which jq >/dev/null 2>&1 || yum install jq -y >/dev/null 2>&1 path0="/cfddns" function messageSend() { message=$1 #your messageSend code } ###################### 监测日志格式 ######################## # 监测日志保存位置 log_file="$path0/cloudflare.log" #日志开关,touch这个文件以打开日志查看脚本执行反馈 logSwitch="$path0/logon" if [ ! -f "$log_file" ];then touch "$log_file";fi log() { if [ -f "$logSwitch" ];then if [ "$1" ]; then echo -e "[$(date)] - $1" >> $log_file fi fi } # 告警文件位置 # 连续多少次失败后发送告警,每分钟检测就是30分钟连续失败则告警一次 alertTime=30 alert_file="$path0/alert" if [ ! -f "$alert_file" ];then touch "$alert_file";fi function AlertLog(){ alertMessage=$1 echo -e "[$(date)] - $1" >> "${alert_file}" if [ "$(grep -w "$alertMessage" "${alert_file}" | wc -l)" == "${alertTime}" ];then messageSend "$HOSTNAME #cfddns $alertMessage 已经连续30分钟出现!" log "ALERT !!!!!!!!!! $alertMessage 已经连续30分钟出现!!!!!!!!!!!" fi } function AlertClear(){ alertMessage=$1 if [ "$alertMessage" != "" ];then sed -i "/$alertMessage/d;/^$/d" "${alert_file}";fi } #获取结果ip function printResult(){ if $(grep -q total_count "${tmpFile}");then jq .result[].$1 "${tmpFile}" | sed 's#"##g' else jq .result.$1 "${tmpFile}" | sed 's#"##g' fi } ############### 授权信息(需修改成你自己的) ################ #APIurl APIurl="https://api.cloudflare.com/client/v4/zones" # CloudFlare 注册邮箱 auth_email="" if [ 123"$auth_email" == 123 ];then AlertLog '脚本内置参数 auth_email :注册邮箱未填入' exit 1 fi AlertClear '脚本内置参数 auth_email' # CloudFlare Global API Key, auth_key="" if [ 123"$auth_key" == 123 ];then AlertLog '脚本内置参数 auth_key :Global API Key未填入' exit 1 fi AlertClear '脚本内置参数 auth_key' # 做 DDNS 的根域名 zone_name="" if [ 123"$zone_name" == 123 ];then AlertLog '脚本内置参数 zone_name :根域名未填入' exit 1 fi AlertClear '脚本内置参数 zone_name' # 根域名id zone_identifier="" if [ 123"$zone_identifier" == 123 ];then AlertLog '脚本内置参数 zone_identifier :根域名id未填入' exit 1 fi AlertClear '脚本内置参数 zone_identifier' # 做 DDNS 的域名,二级域名,比如 www.cloudflare.com 的 www record_name="$1" if [ 123"$record_name" == 123 ];then AlertLog '脚本参数1:二级域名缺失' exit 1 fi AlertClear '脚本参数1' # 域名类型,IPv4 为 A,IPv6 则是 AAAA record_type="A" #二级域名id record_identifier_file="$path0/record_identifier.ids" ###################### 修改配置信息 ####################### # IPv6 检测服务,本站检测服务仅在大陆提供 #ip=$(curl -s https://ipv6.vircloud.net) # IPv4 检测服务 curl -s http://ipv4.icanhazip.com ipAPI1="https://ipv4.icanhazip.com" ipAPI2="http://ifconfig.me" # 变动前的公网 IP 保存位置 if [ ! -f "$path0" ];then mkdir -p "$path0" ;fi ip_file="$path0/ip.txt" if [ ! -f "$ip_file" ];then touch "$ip_file";fi # api返回信息结果临时文件 tmpFile="$path0/tmp" log "检测开始……" ip=$(curl -s "$ipAPI1") if ! $(echo "${ip}" | egrep -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$');then log "获取外网ip错误,接口爲 $ipAPI1 ,尝试从服务器获取……" ip=$(curl -s "$ipAPI2") if ! $(echo "${ip}" | egrep -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$');then AlertLog "获取外网IP" exit 1 fi fi AlertClear "获取外网IP" function getResult(){ action=$1 log "操作类型:$action\tAPI结果处理……" #检测结果文件 if [ ! -f "$tmpFile" ];then log "操作类型:$action\t获取结果文件丢失,等待下次处理";return 1;fi #api错误类 log "操作类型:$action\tAPI结果数据处理1……" success=$(jq .success "${tmpFile}" | sed 's#"##g') total_count=$(jq .result_info.total_count "${tmpFile}" | sed 's#"##g') #检测api返回结果,success 或 total_count 爲空则返回 if [ "${success}" == "null" ] || [ "${success}" != "true" ];then errorCode=$(jq .errors[].code "${tmpFile}" | sed 's#"##g') errorMessage=$(jq .errors[].message "${tmpFile}" | sed 's#"##g') APIErrors="errors\tcode:${errorCode}\tmessage:${errorMessage}" log "操作类型:$action\t获取结果:\t${APIErrors},获取失败,分析错误代码……" case "${errorCode}" in "81044") log "操作类型:$action\t线上不存在记录" return 0 ;; *) log "操作类型:$action\t${errorMessage}" ;; esac AlertLog "API请求错误 ${APIErrors}" return 1 fi AlertClear "API请求错误" #检测返回个数 log "操作类型:$action\tAPI结果数据处理2……" if [ "${total_count}" == "0" ];then log "操作类型:$action\t获取结果:\t0,没有查询到信息";return 0;fi #超过一个结果 if [ "${total_count}" != "null" ] && [ "${total_count}" -gt "1" ];then if [ "$action" == "recheck" ];then #检测操作 爲cf线上错误,直接返回 log "操作类型:$action\t获取结果:\t爲CF线上错误,id ${total_count} 个数爲 ${total_count}" messageSend "$HOSTNAME #cfddns CF线上错误 id $2 查询到了2个记录!" return 1 elif [ "$action" == "search" ];then #搜索操作 只保留一个 log "操作类型:$action\t获取结果:查询域名解析个数爲 ${total_count} 个" record_id="" for record in $(printResult id) ;do if [ "$record_id" == "" ];then #获取一个id record_id=$record log "操作类型:$action\t获取结果:保留 id 爲 ${total_count} 的解析" else #其馀删除 log "操作类型:$action\t获取结果:删除 id 爲 ${total_count} 的解析" curl -s -X DELETE "$APIurl/${zone_identifier}/dns_records/${record}" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" >/dev/null 2>&1 fi done echo "$record_id" return 0 fi fi #返回结果 log "操作类型:$action\tAPI结果数据处理完成……" printResult id return 0 } function getrecord_id(){ log "本地数据检测……" record_identifier="" if [ -f "$record_identifier_file" ];then #获取本地解析id log "尝试获取本地记录id……" record_identifier=$(cat "$record_identifier_file") record_count=$(echo $record_identifier | sed 's# #\n#g' | wc -l) if [ "$record_count" != "1" ];then #本地数据 异常:爲空;多个数值 log "本地数据错误……" log "本地id信息错误,重置本地数据" record_identifier="" #重置数据 cd . > "$record_identifier_file" elif [ "$record_identifier" != "" ];then #本地数据 正常 #验证线上数据 log "以本地数据检测线上数据……" curl -s -X GET "$APIurl/${zone_identifier}/dns_records/${record_identifier}" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" >"${tmpFile}" 2>&1 #再次获取id record_identifier=$(getResult recheck "${record_identifier}") if [ $? == 1 ];then log "线上数据获取错误,等待下次检测";return 1 fi if [ "$(printResult name)" != "${record_name}.${zone_name}" ];then log "本地数据和待处理域名不匹配,重置本地数据……" record_identifier="" #重置数据 cd . > "$record_identifier_file" fi fi fi #如果异常 if [ "${record_identifier}" == "" ];then #本地数据爲空 log "id爲空,尝试搜索线上是否存在域名解析数据……" #搜索线上解析鬱闷 curl -s -X GET "$APIurl/${zone_identifier}/dns_records?name=${record_name}.${zone_name}&proxied=false&type=$record_type" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" > "${tmpFile}" 2>&1 record_identifier=$(getResult search) if [ $? == 0 ];then if [ "$record_identifier" != "" ];then #搜索到了 log "线上id获取成功!写入本地记录……" echo "$record_identifier" > $record_identifier_file return 0 else #没有搜索到记录 则新增 log "没有查询到记录,尝试新增……" curl -s -X POST "$APIurl/$zone_identifier/dns_records" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"type\":\"$record_type\",\"name\":\"${record_name}.${zone_name}\",\"content\":\"$ip\",\"ttl\":120,\"proxied\":false}" > "${tmpFile}" 2>&1 record_identifier=$(getResult recheck) if [ $? == 0 ] && [ "${record_identifier}" != "" ];then log "新增成功!写入本地记录……" messageSend "$HOSTNAME #cfddns $1 新增解析成功,当前IP:$ip!" echo "$record_identifier" > $record_identifier_file return 0 fi fi fi return 1 fi #如果查询到了 return 0 } ###################### 获取域名授权及新增 ###################### getrecord_id if [ $? == 1 ];then exit 1;fi log "数据获取成功……" if [ "$ipOnline" == "" ];then ipOnline=$(printResult content) fi ###################### 判断 IP 是否变化 #################### if [ -f "$ip_file" ]; then old_ip=$(cat "$ip_file") #如果查询ip等于本地存储ip if [ "$ip" == "$old_ip" ] && [ "$ip" == "$ipOnline" ]; then log "IP has not changed." exit 0 fi if [ "$ip" == "$ipOnline" ] && [ "$ip" != "$old_ip" ];then log "ip正常,修正本地数据……" echo "$ip" > "$ip_file" exit 0 fi fi ###################### 更新 DNS 记录 ###################### log "ip变动,修正线上数据……" curl -s -X PUT "$APIurl/$zone_identifier/dns_records/$record_identifier" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"type\":\"$record_type\",\"name\":\"${record_name}.${zone_name}\",\"content\":\"$ip\",\"ttl\":120,\"proxied\":false}" >/dev/null 2>&1 record_identifier=$(getResult recheck "${record_identifier}") if [ $? == 0 ];then result_ip=$(printResult content) if [ "$ip" == "$result_ip" ];then log "修正线上数据成功,写入本地……" messageSend "$HOSTNAME #cfddns $1 解析修改成功,当前IP:$ip!" echo "$ip" > "$ip_file" exit 0 fi fi log "处理完成!"
© 著作权归作者所有
下一篇: cnbeta rss 内容解析
文章评论(0)