Skip to content

Instantly share code, notes, and snippets.

@fbigun
Forked from zrong/dnspodsh.sh
Last active August 29, 2015 14:06
Show Gist options
  • Select an option

  • Save fbigun/225d964b9111bb5c5eac to your computer and use it in GitHub Desktop.

Select an option

Save fbigun/225d964b9111bb5c5eac to your computer and use it in GitHub Desktop.

Revisions

  1. @zrong zrong revised this gist Feb 1, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -30,7 +30,7 @@ domainList[1]='domain2.com subdomain subdomain2'
    delay=300

    # logfile
    logDir='var/log'
    logDir='/var/log'
    logFile=$logDir'/dnspodsh.log'
    traceFile=$logDir'/dnspodshtrace.log'

  2. @zrong zrong revised this gist Dec 24, 2012. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -37,8 +37,12 @@ traceFile=$logDir'/dnspodshtrace.log'
    # 检测ip地址是否符合要求
    checkip()
    {
    # ipv4地址
    if [[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]];then
    return 0
    # ipv6地址
    elif [[ "$1" =~ ^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}$|^:((:[\da-fA-F]{1,4}){1,6}|:)$|^[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,5}|:)$|^([\da-fA-F]{1,4}:){2}((:[\da-fA-F]{1,4}){1,4}|:)$|^([\da-fA-F]{1,4}:){3}((:[\da-fA-F]{1,4}){1,3}|:)$|^([\da-fA-F]{1,4}:){4}((:[\da-fA-F]{1,4}){1,2}|:)$|^([\da-fA-F]{1,4}:){5}:([\da-fA-F]{1,4})?$|^([\da-fA-F]{1,4}:){6}:$ ]];then
    return 0
    fi
    return 1
    }
    @@ -277,4 +281,4 @@ go()
    while [ 1 ];do
    go
    sleep $delay
    done
    done
  3. @zrong zrong revised this gist Mar 12, 2012. 1 changed file with 9 additions and 1 deletion.
    10 changes: 9 additions & 1 deletion dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,6 @@ ipUrl='http://members.3322.org/dyndns/getip'
    domainList[0]='domain1.com \* @ www'
    domainList[1]='domain2.com subdomain subdomain2'


    # 多长时间比较一次ip地址
    delay=300

    @@ -160,6 +159,7 @@ checkStatusCode()
    writeLog "DNSPOD return error:$1"
    # 根据参数需求退出程序
    if [ -n "$2" ] && [ "$2" -eq 1 ];then
    writeLog 'exit dnspodsh'
    exit 1
    fi
    }
    @@ -169,6 +169,10 @@ getChangedRecords()
    {
    # 从DNSPod获取最新的域名列表
    local domainListInfo=$(getDomainList)
    if [ -z "$domainListInfo" ];then
    writeLog 'DNSPOD tell me domain list is null,waiting...'
    return 1
    fi
    checkStatusCode "$domainListInfo" 1

    # 主域名的id
    @@ -207,6 +211,10 @@ getChangedRecords()
    domainInfo=$(echo $domainListInfo|getJSONObjByKey 'name' $domainName)
    domainid=$(getDataByKey "$domainInfo" 'id')
    recordList=$(getRecordList $domainid)
    if [ -z "$recordList" ];then
    writeLog 'DNSPOD tell me record list null,waiting...'
    return 1
    fi
    checkStatusCode "$recordList" 1
    else
    # 从dnspod获取要设置的子域名记录的信息
  4. @zrong zrong revised this gist Mar 11, 2012. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -1,19 +1,19 @@
    #!/bin/bash

    ##############################
    # dnspodsh
    # dnspodsh v0.3
    # 基于dnspod api构架的bash ddns客户端
    # 作者:zrong(zengrong.net)
    # 详细介绍:http://zengrong.net/post/1524.htm
    # 创建日期:2012-02-13
    # 更新日期:2012-03-10
    # 更新日期:2012-03-11
    ##############################

    login_email=${1:?'必须提供登录名'}
    login_password=${2:?'必须提供密码'}
    format="json"
    lang="en"
    userAgent="dnspodsh/0.2(zrongzrong@gmail.com)"
    userAgent="dnspodsh/0.3(zrongzrong@gmail.com)"
    commonPost="login_email=$login_email&login_password=$login_password&format=$format&lang=$lang"

    apiUrl='https://dnsapi.cn/'
  5. @zrong zrong revised this gist Mar 11, 2012. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -4,6 +4,7 @@
    # dnspodsh
    # 基于dnspod api构架的bash ddns客户端
    # 作者:zrong(zengrong.net)
    # 详细介绍:http://zengrong.net/post/1524.htm
    # 创建日期:2012-02-13
    # 更新日期:2012-03-10
    ##############################
  6. @zrong zrong revised this gist Mar 11, 2012. 1 changed file with 55 additions and 19 deletions.
    74 changes: 55 additions & 19 deletions dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -25,6 +25,7 @@ ipUrl='http://members.3322.org/dyndns/getip'
    domainList[0]='domain1.com \* @ www'
    domainList[1]='domain2.com subdomain subdomain2'


    # 多长时间比较一次ip地址
    delay=300

    @@ -33,6 +34,15 @@ logDir='var/log'
    logFile=$logDir'/dnspodsh.log'
    traceFile=$logDir'/dnspodshtrace.log'

    # 检测ip地址是否符合要求
    checkip()
    {
    if [[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]];then
    return 0
    fi
    return 1
    }

    getUrl()
    {
    #curl -s -A $userAgent -d $commonPost$2 --trace $traceFile $apiUrl$1
    @@ -58,6 +68,7 @@ writeLog()
    done
    echo -e $pre>>$logFile
    fi
    echo -e $1
    }

    getDomainList()
    @@ -76,23 +87,26 @@ getRecordList()
    setRecord()
    {
    writeLog "set domain $3.$8 to new ip:$7"
    #echo "set domain $3.$8 to new ip:$7"
    local subDomain=$3
    # 由于*会被扩展,在最后一步将转义的\*替换成*
    if [ $subDomain = '\*' ];then
    if [ "$subDomain" = '\*' ];then
    subDomain='*'
    fi
    local request="&domain_id=$1&record_id=$2&sub_domain=$subDomain&record_type=$4&record_line=$5&ttl=$6&value=$7"
    #echo $request
    getUrl 'Record.Modify' $request
    local saveResult=$(getUrl 'Record.Modify' "$request")
    # 检测返回是否正常,但即使不正常也不退出程序
    if checkStatusCode "$saveResult" 0;then
    writeLog "set record $3.$8 success."
    fi
    #getUrl 'Record.Modify' "&domain_id=$domainid&record_id=$recordid&sub_domain=$recordName&record_type=$recordtype&record_line=$recordline&ttl=$recordttl&value=$newip"
    }

    # 设置一批记录
    setRecords()
    {
    numRecord=${#changedRecords[@]}
    for ((i=0;i<$numRecord;i++));do
    for (( i=0; i < $numRecord; i++ ));do
    setRecord ${changedRecords[$i]}
    done
    # 删除待处理的变量
    @@ -134,22 +148,27 @@ getJSONObjByARecord()
    grep -o '{[^}{]*"name":"'$1'"[^}]*"type":"A"[^}]*}'
    }

    # 获取返回代码是否正确,任何情况下,如果碰到这个代码错误,就停止程序。因为dnspod在代码错误过多的情况下会封禁账号
    # 获取返回代码是否正确
    # $1 要检测的字符串,该字符串包含{status:{code:1}}形式,代表DNSPodAPI返回正确
    # $2 是否要停止程序,因为dnspod在代码错误过多的情况下会封禁账号
    checkStatusCode()
    {
    if [ "echo $1|grep '{"status":{[^}{]*"code":"1"[^}]*}'" ];then
    if [[ "$1" =~ \{\"status\":\{[^}{]*\"code\":\"1\"[^}]*\} ]];then
    return 0
    fi
    writeLog 'DNSPOD return error:'$1
    exit 1
    writeLog "DNSPOD return error:$1"
    # 根据参数需求退出程序
    if [ -n "$2" ] && [ "$2" -eq 1 ];then
    exit 1
    fi
    }

    # 获取与当前ip不同的,要更新的记录的数组
    getChangedRecords()
    {
    # 从DNSPod获取最新的域名列表
    local domainListInfo=$(getDomainList)
    checkStatusCode "$domainListInfo"
    checkStatusCode "$domainListInfo" 1

    # 主域名的id
    local domainid
    @@ -187,15 +206,24 @@ getChangedRecords()
    domainInfo=$(echo $domainListInfo|getJSONObjByKey 'name' $domainName)
    domainid=$(getDataByKey "$domainInfo" 'id')
    recordList=$(getRecordList $domainid)
    checkStatusCode "$recordList"
    checkStatusCode "$recordList" 1
    else
    # 从dnspod获取要设置的子域名记录的信息
    recordInfo=$(echo $recordList|getJSONObjByARecord $domain)
    checkStatusCode "$recordInfo"
    # 如果取不到记录,则不处理
    if [ -z "$recordInfo" ];then
    continue
    fi

    # 从dnspod获取要设置的子域名的ip
    oldip=$(getDataByKey "$recordInfo" 'value')

    # 检测获取到的旧ip地址是否符合ip规则
    if ! checkip "$oldip";then
    writeLog 'get old ip error!it is "$oldid".waiting...'
    continue
    fi

    if [ "$newip" != "$oldip" ];then
    recordid=$(getDataByKey "$recordInfo" 'id')
    recordName=$(getDataByKey "$recordInfo" 'name')
    @@ -204,32 +232,40 @@ getChangedRecords()
    # 由于从服务器获取的线路是utf编码,目前无法知道如何转换成中文,因此在这里写死。dnspod中免费用户的默认线路的名称就是“默认”
    #recordLine=$(getDataByKey "$recordInfo" 'line')
    recordLine='默认'
    # 使用数组记录需要修改的子域名的所有值
    # 这里一共有8个参数,与setRecord中的参数对应
    changedRecords[${#changedRecords[@]}]="$domainid $recordid $domain $recordType $recordLine $recordTtl $newip $domainName"
    # 判断取值是否正常,如果值为空就不处理
    if [ -n "$recordid" ] && [ -n "$recordTtl" ] && [ -n "$recordType" ]; then
    # 使用数组记录需要修改的子域名的所有值
    # 这里一共有8个参数,与setRecord中的参数对应
    changedRecords[${#changedRecords[@]}]="$domainid $recordid $domain $recordType $recordLine $recordTtl $newip $domainName"
    fi
    fi
    fi
    j=$((j+1))
    done
    done
    }

    while [ 1 ];do
    # 执行检测工作
    go()
    {
    # 由于获取到的数据多了一些多余的字符,所以提取ip地址的部分
    # 从api中获取当前的外网ip
    newip=$(curl -s $ipUrl|grep -o $(getRegexp 'value'))
    echo $newip
    # 如果获取最新ip错误,就继续等待下一次取值
    if ! [[ "$newip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]];then
    if ! checkip "$newip";then
    writeLog 'can not get new ip,waiting...'
    sleep $delay
    continue
    fi
    # 获取需要修改的记录
    getChangedRecords
    if ((${#changedRecords[@]}>0));then
    writelog 'ip is changed,new ip is:'$newip
    if (( ${#changedRecords[@]} > 0 ));then
    writeLog "ip is changed,new ip is:$newip"
    setRecords
    fi
    }

    while [ 1 ];do
    go
    sleep $delay
    done
  7. @zrong zrong revised this gist Mar 10, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -226,7 +226,7 @@ while [ 1 ];do
    continue
    fi
    # 获取需要修改的记录
    getChangedRecords $newip
    getChangedRecords
    if ((${#changedRecords[@]}>0));then
    writelog 'ip is changed,new ip is:'$newip
    setRecords
  8. @zrong zrong revised this gist Mar 10, 2012. 1 changed file with 1 addition and 3 deletions.
    4 changes: 1 addition & 3 deletions dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -147,8 +147,6 @@ checkStatusCode()
    # 获取与当前ip不同的,要更新的记录的数组
    getChangedRecords()
    {
    # 新的ip
    local newip=$1
    # 从DNSPod获取最新的域名列表
    local domainListInfo=$(getDomainList)
    checkStatusCode "$domainListInfo"
    @@ -222,7 +220,7 @@ while [ 1 ];do
    newip=$(curl -s $ipUrl|grep -o $(getRegexp 'value'))
    echo $newip
    # 如果获取最新ip错误,就继续等待下一次取值
    if [ -z $newip ];then
    if ! [[ "$newip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]];then
    writeLog 'can not get new ip,waiting...'
    sleep $delay
    continue
  9. @zrong zrong revised this gist Mar 10, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -26,7 +26,7 @@ domainList[0]='domain1.com \* @ www'
    domainList[1]='domain2.com subdomain subdomain2'

    # 多长时间比较一次ip地址
    delay=5
    delay=300

    # logfile
    logDir='var/log'
  10. @zrong zrong revised this gist Mar 10, 2012. 1 changed file with 130 additions and 61 deletions.
    191 changes: 130 additions & 61 deletions dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -4,35 +4,39 @@
    # dnspodsh
    # 基于dnspod api构架的bash ddns客户端
    # 作者:zrong(zengrong.net)
    # 日期:2012-02-13
    # 创建日期:2012-02-13
    # 更新日期:2012-03-10
    ##############################

    login_email=${1:?'必须提供登录名'}
    login_password=${2:?'必须提供密码'}
    format="json"
    lang="en"
    userAgent="dnspodsh/0.1(zrongzrong@gmail.com)"
    userAgent="dnspodsh/0.2(zrongzrong@gmail.com)"
    commonPost="login_email=$login_email&login_password=$login_password&format=$format&lang=$lang"

    apiUrl='https://dnsapi.cn/'
    ipUrl='http://members.3322.org/dyndns/getip'

    # 要处理的域名
    domainName='yourname.net'
    # 要处理的子域名
    recordName='www'
    # 搜索到的子域名的信息
    record='初始值'
    # 要处理的域名数组,每个元素代表一个域名的一组记录
    # 在数组的一个元素中,以空格分隔域名和子域名
    # 第一个空格前为主域名,后面用空格分离多个子域名
    # 如果使用泛域名,必须用\*转义
    domainList[0]='domain1.com \* @ www'
    domainList[1]='domain2.com subdomain subdomain2'

    # 多长时间比较一次ip地址
    delay=300
    delay=5

    # logfile
    logFile=/var/log/dnspodsh.log
    logDir='var/log'
    logFile=$logDir'/dnspodsh.log'
    traceFile=$logDir'/dnspodshtrace.log'

    getUrl()
    {
    curl -s -A $userAgent -d $commonPost$2 --trace trace.txt $apiUrl$1
    #curl -s -A $userAgent -d $commonPost$2 --trace $traceFile $apiUrl$1
    curl -s -A $userAgent -d $commonPost$2 $apiUrl$1
    }

    getVersion()
    @@ -47,11 +51,13 @@ getUserDetail()

    writeLog()
    {
    local pre=`date`
    for arg in $@;do
    pre=$pre'\t'$arg
    done
    echo -e $pre>>$logFile
    if [ -w $logDir ];then
    local pre=`date`
    for arg in $@;do
    pre=$pre'\t'$arg
    done
    echo -e $pre>>$logFile
    fi
    }

    getDomainList()
    @@ -69,11 +75,28 @@ getRecordList()
    # 设置记录
    setRecord()
    {
    writeLog '设置新记录'
    getUrl 'Record.Modify' "&domain_id=$domainid&record_id=$recordid&sub_domain=$recordName&record_type=$recordtype&record_line=$recordline&ttl=$recordttl&value=$newip"
    sleep 10
    # 再次通过dnspod的api获取最新的数据
    getInitValue
    writeLog "set domain $3.$8 to new ip:$7"
    #echo "set domain $3.$8 to new ip:$7"
    local subDomain=$3
    # 由于*会被扩展,在最后一步将转义的\*替换成*
    if [ $subDomain = '\*' ];then
    subDomain='*'
    fi
    local request="&domain_id=$1&record_id=$2&sub_domain=$subDomain&record_type=$4&record_line=$5&ttl=$6&value=$7"
    #echo $request
    getUrl 'Record.Modify' $request
    #getUrl 'Record.Modify' "&domain_id=$domainid&record_id=$recordid&sub_domain=$recordName&record_type=$recordtype&record_line=$recordline&ttl=$recordttl&value=$newip"
    }

    # 设置一批记录
    setRecords()
    {
    numRecord=${#changedRecords[@]}
    for ((i=0;i<$numRecord;i++));do
    setRecord ${changedRecords[$i]}
    done
    # 删除待处理的变量
    unset changeRecords
    }

    # 通过key得到找到一个JSON对象字符串中的值
    @@ -90,7 +113,7 @@ getRegexp()
    case $1 in
    'value') echo '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}';;
    'type') echo '[A-Z]\+';;
    'name') echo '[-_.A-Za-z]\+';;
    'name') echo '[-_.A-Za-z*]\+';;
    'ttl'|'id') echo '[0-9]\+';;
    'line') echo '[^"]\+';;
    esac
    @@ -104,65 +127,111 @@ getJSONObjByKey()
    grep -o '{[^}{]*"'$1'":"'$2'"[^}]*}'
    }

    # 获取A记录类型的域名信息
    # 对于其它记录,同样的名称可以对应多条记录,因此使用getJSONObjByKey可能获取不到需要的数据
    getJSONObjByARecord()
    {
    grep -o '{[^}{]*"name":"'$1'"[^}]*"type":"A"[^}]*}'
    }

    # 获取返回代码是否正确,任何情况下,如果碰到这个代码错误,就停止程序。因为dnspod在代码错误过多的情况下会封禁账号
    checkStatusCode()
    {
    if [ "echo $1|grep '{"status":{[^}{]*"code":"1"[^}]*}'" ];then
    return 0
    fi
    writeLog 'DNSPOD返回错误:'$1
    writeLog 'DNSPOD return error:'$1
    exit 1
    }

    getInitValue()
    # 获取与当前ip不同的,要更新的记录的数组
    getChangedRecords()
    {
    domainList=$(getDomainList)
    checkStatusCode "$domainList"

    # 从dnspod获取要设置的域名的信息
    domainInfo=$(echo $domainList|getJSONObjByKey 'name' $domainName)

    # 获取域名的id
    domainid=$(getDataByKey "$domainInfo" 'id')

    recordList=$(getRecordList $domainid)
    checkStatusCode "$recordList"

    # 从dnspod获取要设置的子域名记录的信息
    recordInfo=$(echo $recordList|getJSONObjByKey 'name' $recordName)

    recordid=$(getDataByKey "$recordInfo" 'id')
    recordttl=$(getDataByKey "$recordInfo" 'ttl')
    recordtype=$(getDataByKey "$recordInfo" 'type')
    #recordline=$(getDataByKey "$recordInfo" 'line')
    # 由于从服务器获取的线路是utf编码,目前无法知道如何转换成中文,因此在这里写死。dnspod中免费用户的默认线路的名称就是“默认”
    recordline='默认'

    # 从dnspod获取要设置的子域名的ip
    oldip=$(getDataByKey "$recordInfo" 'value')
    writeLog '初始化数据'
    # 新的ip
    local newip=$1
    # 从DNSPod获取最新的域名列表
    local domainListInfo=$(getDomainList)
    checkStatusCode "$domainListInfo"

    # 主域名的id
    local domainid
    local domainName
    # 主域名的JSON信息
    local domainInfo
    # 主域名的所有记录列表
    local recordList
    # 一条记录的JSON信息
    local recordInfo
    # 记录的id
    local recordid
    local recordName
    # 记录的TTL
    local recordTtl
    # 记录的类型
    local recordType
    # 记录的线路
    local recordLine
    local j

    # 用于记录被改变的记录
    unset changedRecords

    local numDomain=${#domainList[@]}
    local domainGroup

    for ((i=0;i<$numDomain;i++));do
    domainGroup=${domainList[$i]}
    j=0
    for domain in ${domainGroup[@]};do
    # 列表的第一个项目,是主域名
    if ((j==0));then
    domainName=$domain
    domainInfo=$(echo $domainListInfo|getJSONObjByKey 'name' $domainName)
    domainid=$(getDataByKey "$domainInfo" 'id')
    recordList=$(getRecordList $domainid)
    checkStatusCode "$recordList"
    else
    # 从dnspod获取要设置的子域名记录的信息
    recordInfo=$(echo $recordList|getJSONObjByARecord $domain)
    checkStatusCode "$recordInfo"

    # 从dnspod获取要设置的子域名的ip
    oldip=$(getDataByKey "$recordInfo" 'value')

    if [ "$newip" != "$oldip" ];then
    recordid=$(getDataByKey "$recordInfo" 'id')
    recordName=$(getDataByKey "$recordInfo" 'name')
    recordTtl=$(getDataByKey "$recordInfo" 'ttl')
    recordType=$(getDataByKey "$recordInfo" 'type')
    # 由于从服务器获取的线路是utf编码,目前无法知道如何转换成中文,因此在这里写死。dnspod中免费用户的默认线路的名称就是“默认”
    #recordLine=$(getDataByKey "$recordInfo" 'line')
    recordLine='默认'
    # 使用数组记录需要修改的子域名的所有值
    # 这里一共有8个参数,与setRecord中的参数对应
    changedRecords[${#changedRecords[@]}]="$domainid $recordid $domain $recordType $recordLine $recordTtl $newip $domainName"
    fi
    fi
    j=$((j+1))
    done
    done
    }

    getInitValue

    if [ -z $oldip ];then
    writeLog '无法取得旧ip,退出程序'
    exit 1
    fi

    while [ 1 ];do
    # 由于获取到的数据多了一些多余的字符,所以提取ip地址的部分
    # 从api中获取当前的外网ip
    newip=$(curl -s $ipUrl|grep -o $(getRegexp 'value'))
    # 如果取值错误,就继续等待下一次取值
    echo $newip
    # 如果获取最新ip错误,就继续等待下一次取值
    if [ -z $newip ];then
    writeLog '取值错误:'$newip
    writeLog 'can not get new ip,waiting...'
    sleep $delay
    continue
    fi
    writeLog 'newip:'$newip 'oldip:'$oldip
    if [ "$newip" != "$oldip" ];then
    setRecord
    # 获取需要修改的记录
    getChangedRecords $newip
    if ((${#changedRecords[@]}>0));then
    writelog 'ip is changed,new ip is:'$newip
    setRecords
    fi
    sleep $delay
    done
  11. @zrong zrong created this gist Feb 14, 2012.
    168 changes: 168 additions & 0 deletions dnspodsh.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,168 @@
    #!/bin/bash

    ##############################
    # dnspodsh
    # 基于dnspod api构架的bash ddns客户端
    # 作者:zrong(zengrong.net)
    # 日期:2012-02-13
    ##############################

    login_email=${1:?'必须提供登录名'}
    login_password=${2:?'必须提供密码'}
    format="json"
    lang="en"
    userAgent="dnspodsh/0.1(zrongzrong@gmail.com)"
    commonPost="login_email=$login_email&login_password=$login_password&format=$format&lang=$lang"

    apiUrl='https://dnsapi.cn/'
    ipUrl='http://members.3322.org/dyndns/getip'

    # 要处理的域名
    domainName='yourname.net'
    # 要处理的子域名
    recordName='www'
    # 搜索到的子域名的信息
    record='初始值'

    # 多长时间比较一次ip地址
    delay=300

    # logfile
    logFile=/var/log/dnspodsh.log

    getUrl()
    {
    curl -s -A $userAgent -d $commonPost$2 --trace trace.txt $apiUrl$1
    }

    getVersion()
    {
    getUrl "Info.Version"
    }

    getUserDetail()
    {
    getUrl "User.Detail"
    }

    writeLog()
    {
    local pre=`date`
    for arg in $@;do
    pre=$pre'\t'$arg
    done
    echo -e $pre>>$logFile
    }

    getDomainList()
    {
    getUrl "Domain.List" "&type=all&offset=0&length=10"
    }

    # 根据域名id获取记录列表
    # $1 域名id
    getRecordList()
    {
    getUrl "Record.List" "&domain_id=$1&offset=0&length=20"
    }

    # 设置记录
    setRecord()
    {
    writeLog '设置新记录'
    getUrl 'Record.Modify' "&domain_id=$domainid&record_id=$recordid&sub_domain=$recordName&record_type=$recordtype&record_line=$recordline&ttl=$recordttl&value=$newip"
    sleep 10
    # 再次通过dnspod的api获取最新的数据
    getInitValue
    }

    # 通过key得到找到一个JSON对象字符串中的值
    getDataByKey()
    {
    local s='s/{[^}]*"'$2'":["]*\('$(getRegexp $2)'\)["]*[^}]*}/\1/'
    #echo '拼合成的regexp:'$s
    echo $1|sed $s
    }

    # 根据key返回要获取的正则表达式
    getRegexp()
    {
    case $1 in
    'value') echo '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}';;
    'type') echo '[A-Z]\+';;
    'name') echo '[-_.A-Za-z]\+';;
    'ttl'|'id') echo '[0-9]\+';;
    'line') echo '[^"]\+';;
    esac
    }

    # 通过一个JSON key名称,获取一个{}包围的JSON对象字符串
    # $1 要搜索的key名称
    # $2 要搜索的对应值
    getJSONObjByKey()
    {
    grep -o '{[^}{]*"'$1'":"'$2'"[^}]*}'
    }

    # 获取返回代码是否正确,任何情况下,如果碰到这个代码错误,就停止程序。因为dnspod在代码错误过多的情况下会封禁账号
    checkStatusCode()
    {
    if [ "echo $1|grep '{"status":{[^}{]*"code":"1"[^}]*}'" ];then
    return 0
    fi
    writeLog 'DNSPOD返回错误:'$1
    exit 1
    }

    getInitValue()
    {
    domainList=$(getDomainList)
    checkStatusCode "$domainList"

    # 从dnspod获取要设置的域名的信息
    domainInfo=$(echo $domainList|getJSONObjByKey 'name' $domainName)

    # 获取域名的id
    domainid=$(getDataByKey "$domainInfo" 'id')

    recordList=$(getRecordList $domainid)
    checkStatusCode "$recordList"

    # 从dnspod获取要设置的子域名记录的信息
    recordInfo=$(echo $recordList|getJSONObjByKey 'name' $recordName)

    recordid=$(getDataByKey "$recordInfo" 'id')
    recordttl=$(getDataByKey "$recordInfo" 'ttl')
    recordtype=$(getDataByKey "$recordInfo" 'type')
    #recordline=$(getDataByKey "$recordInfo" 'line')
    # 由于从服务器获取的线路是utf编码,目前无法知道如何转换成中文,因此在这里写死。dnspod中免费用户的默认线路的名称就是“默认”
    recordline='默认'

    # 从dnspod获取要设置的子域名的ip
    oldip=$(getDataByKey "$recordInfo" 'value')
    writeLog '初始化数据'
    }

    getInitValue

    if [ -z $oldip ];then
    writeLog '无法取得旧ip,退出程序'
    exit 1
    fi

    while [ 1 ];do
    # 由于获取到的数据多了一些多余的字符,所以提取ip地址的部分
    # 从api中获取当前的外网ip
    newip=$(curl -s $ipUrl|grep -o $(getRegexp 'value'))
    # 如果取值错误,就继续等待下一次取值
    if [ -z $newip ];then
    writeLog '取值错误:'$newip
    sleep $delay
    continue
    fi
    writeLog 'newip:'$newip 'oldip:'$oldip
    if [ "$newip" != "$oldip" ];then
    setRecord
    fi
    sleep $delay
    done