You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:53:00