问题背景

在小米路由器中配置阿里云DDNS时,教程参考的是 ,执行脚本出现 -ash: /data/scripts/aliyun_ddns.sh: not found 错误,但确认文件存在且路径正确。以下是问题排查和修复过程。


遇到的坑及解决方案

1. 文件换行符问题(CRLF → LF)

  • 现象 :脚本在Windows编辑后上传,换行符为 CRLF ,导致Linux无法识别。
  • 解决 :用 Sublime Text 将换行符转为 Unix (LF)
    1. 打开脚本文件 → 右下角点击 CRLF → 选择 Unix (LF)
    2. 保存后重新上传到路由器。

2. BusyBox Ash Shell 兼容性问题

  • 现象 /bin/sh 指向 BusyBox,不支持 function 关键字。
  • 解决 :删除所有 function 关键字:
    # 错误写法functiongetMachine_IPv4(){... }# 正确写法getMachine_IPv4(){... }

3. 命令路径未指定绝对路径

  • 现象 ip , grep , awk 等命令因路径问题无法调用。
  • 解决 :替换为绝对路径(根据 command -v 检查结果):
    # 修改前ipv6=$(ip addr |grep"inet6")# 修改后ipv6=$(/sbin/ip addr | /bin/grep "inet6")

4. 变量未加引号导致解析错误

  • 现象 enc $machine_ip 在IP含特殊字符时报错。
  • 解决 :变量用双引号包裹:
    # 修改前Value=$(enc $machine_ip)# 修改后Value=$(enc "$machine_ip")

完整修复代码(可直接复制)

#!/bin/shset-e# 参数配置(替换为你自己的信息)aliddns_ak="<Your_AccessKey>"aliddns_sk="<Your_SecretKey>"aliddns_subdomain="<Subdomain>"aliddns_domain="<Your_Domain>"aliddns_iptype="A"# A或AAAAaliddns_ttl=600#--------------------------------------------------------------# 函数定义#--------------------------------------------------------------getMachine_IPv4(){echo$(/usr/bin/wget -qO- -t1-T2)}getMachine_IPv6(){ipv6=$(/sbin/ip addr | /bin/grep "inet6.*global"| /bin/grep -v"deprecated"| /usr/bin/awk '{print $2}'| /usr/bin/awk -F"/"'{print $1}'| /bin/sed -n'1,1p')echo$ipv6}getDDNS_IP(){current_ip=$(/usr/bin/nslookup -query=$aliddns_iptype $aliddns_name | /bin/grep "Address"| /bin/grep -v"#53"| /usr/bin/awk '{print $2}')echo$current_ip}urlencode(){out=""whileread-n1 c
    docase$cin[a-zA-Z0-9._-])out="$out$c";;
            *)out="$out$(printf'%%%02X'"'$c")";;esacdoneecho-n$out}enc(){echo-n"$1"| urlencode
}send_request(){localargs="AccessKeyId=$aliddns_ak&Action=$1&Format=json&$2&Version=2015-01-09"localhash=$(echo-n"GET&%2F&$(enc "$args")"| /usr/bin/openssl dgst -sha1-hmac"$aliddns_sk&"-binary| /usr/bin/openssl base64)
    /usr/bin/curl -s"$args&Signature=$(enc "$hash")"}get_recordid(){
    /bin/grep -Eo'"RecordId":"[0-9]+"'| /usr/bin/cut -d':'-f2| /usr/bin/tr -d'"'}query_recordid(){
    send_request "DescribeSubDomainRecords""SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$aliddns_name&Timestamp=$timestamp&Type=$aliddns_iptype"}update_record(){
    send_request "UpdateDomainRecord""RR=$aliddns_subdomain&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$aliddns_ttl&Timestamp=$timestamp&Type=$aliddns_iptype&Value=$(enc "$machine_ip")"}add_record(){
    send_request "AddDomainRecord&DomainName=$aliddns_domain""RR=$aliddns_subdomain&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$aliddns_ttl&Timestamp=$timestamp&Type=$aliddns_iptype&Value=$(enc "$machine_ip")"}#--------------------------------------------------------------# 主流程#--------------------------------------------------------------if["$aliddns_subdomain"="@"];thenaliddns_name=$aliddns_domainelsealiddns_name=$aliddns_subdomain.$aliddns_domainfinow=$(date)echo"**************************************************"echo"$now"echo"$aliddns_name"if["$aliddns_iptype"='A'];thenecho"ddns is IPv4."machine_ip=$(getMachine_IPv4)echo"machine_ip = $machine_ip"aliddns_record_id=$aliddnsipv4_record_idelseecho"ddns is IPv6."machine_ip=$(getMachine_IPv6)echo"machine_ip = $machine_ip"aliddns_record_id=$aliddnsipv6_record_idfiddns_ip=$(getDDNS_IP)echo"ddns_ip = $ddns_ip"if[-z"$machine_ip"];thenecho"machine_ip is empty!"exit0fiif["$machine_ip"="$ddns_ip"];thenecho"skipping"exit1fiecho"start update..."timestamp=$(date-u"+%Y-%m-%dT%H%%3A%M%%3A%SZ")if[-z"$aliddns_record_id"];thenaliddns_record_id=$(query_recordid | get_recordid)echo"---------------- $aliddns_record_id"if["$aliddns_iptype"='A'];thenaliddnsipv4_record_id=$aliddns_record_idelsealiddnsipv6_record_id=$aliddns_record_idfifiif[-z"$aliddns_record_id"];thenecho"add record starting"aliddns_record_id=$(add_record | get_recordid)if[-z"$aliddns_record_id"];thenecho"aliddns_record_id is empty."elseif["$aliddns_iptype"='A'];thenaliddnsipv4_record_id=$aliddns_record_idelsealiddnsipv6_record_id=$aliddns_record_idfiecho"added record $aliddns_record_id"fielseecho"update record starting"
    update_record $aliddns_record_idecho"updated record $aliddns_record_id"fi

使用步骤

  1. 将脚本保存为 aliyun_ddns.sh ,替换 <Your_AccessKey> , <Your_Domain> 等参数。
  2. 上传到小米路由器 /data/scripts 目录。
  3. 赋予执行权限:
    chmod +x /data/scripts/aliyun_ddns.sh
    
  4. 手动运行测试:
    /data/scripts/aliyun_ddns.sh
    

总结

通过修复换行符、适配 BusyBox 语法、指定绝对路径和变量引号,最终成功在小米路由器上运行阿里云DDNS脚本。希望这篇分享能帮你少走弯路!