Bash脚本无法创建缓存文件,无指定提示输出求助(GoDaddy DDNS)
排查GoDaddy DDNS脚本的几个关键问题
我仔细梳理了你的脚本,发现几个直接导致你遇到的问题(还有不少潜在逻辑漏洞)的点,咱们一步步来解决:
1. 参数判断与赋值的低级错误
你的脚本开头写了if [ $# -ne 2 ];来判断参数数量,但usage提示里明确要求3个参数(记录类型、记录名称、域名),比如$0 AAAA www my_domain。这会导致你正常传3个参数时,脚本直接输出用法提示就退出了,根本走不到IP检查的逻辑。同时,你把$1赋值给name、$2赋值给domain,完全忽略了用户传入的记录类型参数,后续所有DNS操作都硬编码为A记录,和你想更新的AAAA记录完全不匹配。
2. IP获取逻辑不匹配记录类型+echo语法错误
如果要更新AAAA记录,你当前的代码只提取IPv4地址:
currentIp=$(echo $ret | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b")
这种情况下即使你的网络有公网IPv6,currentIp也会是空值,但你输出提示的语句有语法错误:
echo $name".$domain": $(date): no ip address, program exit"
末尾多了一个多余的双引号,导致这条echo命令直接报错,根本无法输出你想要的提示——这就是你看不到那句信息的直接原因!
3. 缓存文件只读取不写入
你的脚本只在开头尝试读取缓存文件:
[ -e $cache ] && old=`cat $cache`
但全程没有在IP更新(甚至首次获取到IP)时把当前IP写入缓存,所以$cache文件永远不会被创建,old变量永远是空值,完全起不到判断IP是否变化的作用。
4. DNS记录查询硬编码为A记录
你查询GoDaddy DNS记录的URL是:
"https://api.godaddy.com/v1/domains/$domain/records/A/$name"
这里硬写了A记录类型,但用户传入的可能是AAAA,这会导致你查询的记录类型和要更新的类型完全不匹配,逻辑彻底混乱。
修改后的完整脚本
我把所有问题都修复了,还优化了一些细节:
#!/bin/bash # 本脚本用于检查并将GoDaddy DNS服务器记录更新为当前网络连接的IP地址。 # # 原PowerShell脚本作者:mfox # 由sanctus移植到bash # 由Binny Chan添加AAAA记录支持 # # 由pollito优化,支持命令行参数并输出日志信息 # # 首先前往GoDaddy开发者网站创建开发者账号并获取密钥和密钥密码 # 请注意有两种类型的密钥和密钥密码——一种用于测试服务器,一种用于生产服务器 # 请获取生产服务器的密钥和密钥密码 # 检查命令行参数是否正确(需要3个:记录类型、记录名称、域名) if [ $# -ne 3 ]; then echo "usage: $0 <record_type> <record_name> <domain_name>" echo "example: $0 AAAA www my_domain.com" echo "example: $0 A @ my_domain.com" exit 1 fi # 赋值命令行参数 record_type=$1 name=$2 domain=$3 cache="/tmp/.mcsync.$name.$domain.$record_type.addr" # 读取缓存中的旧IP(如果缓存存在) old_ip="" if [ -e "$cache" ]; then old_ip=$(cat "$cache") fi # 填入你的GoDaddy API密钥和密钥密码 key="your_api_key_here" secret="your_api_secret_here" headers="Authorization: sso-key $key:$secret" # 根据记录类型获取对应的公网IP current_ip="" if [ "$record_type" = "A" ]; then # 获取IPv4地址 ret=$(curl -s "http://ipinfo.io/json") current_ip=$(echo "$ret" | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b") elif [ "$record_type" = "AAAA" ]; then # 获取IPv6地址(使用IPv6接口) ret=$(curl -s "http://ipinfo.io/json" -6) current_ip=$(echo "$ret" | grep -oE "([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}") fi # 检查IP地址是否为空 if [ -z "$current_ip" ]; then echo "$name.$domain: $(date): no ip address, program exit" exit 1 fi # 检查缓存中的IP是否与当前IP一致,一致则退出 if [ "$old_ip" = "$current_ip" ]; then echo "$name.$domain: $(date): address unchanged, program exit - $current_ip" exit 0 else echo "$name.$domain: $(date): current IP: $current_ip" fi # 获取GoDaddy DNS中当前的记录IP result=$(curl -s -k -X GET -H "$headers" \ "https://api.godaddy.com/v1/domains/$domain/records/$record_type/$name") dns_ip=$(echo "$result" | grep -oE "([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}|([0-9]{1,3}\.){3}[0-9]{1,3}") echo "$name.$domain: $(date): DNS record IP: $dns_ip" # 如果DNS IP与当前IP不一致则更新 if [ "$dns_ip" != "$current_ip" ]; then echo "$name.$domain: $(date): IPs not equal. Updating..." request='{"data":"'$current_ip'","ttl":3600}' nresult=$(curl -i -k -s -X PUT \ -H "$headers" \ -H "Content-Type: application/json" \ -d "$request" "https://api.godaddy.com/v1/domains/$domain/records/$record_type/$name") # 更新缓存文件,写入当前IP echo "$current_ip" > "$cache" echo "$name.$domain: $(date): IP updated successfully to $current_ip" fi
额外注意事项
- 请替换脚本中的
your_api_key_here和your_api_secret_here为你实际的GoDaddy生产环境API密钥和密钥。 - 若要使用IPv6(AAAA记录),请确保你的Raspbian系统已经启用了IPv6网络,否则
curl -6会失败。 - 缓存文件名现在包含了记录类型,避免A和AAAA记录共用缓存导致的判断冲突。
内容的提问来源于stack exchange,提问作者UnluckyForSome
相关产品推荐
相关产品推荐

