华硕路由器开机自动运行自定义脚本实现hosts即时生效的方法之123 2021年2月2日
一、需求
随着家庭网络内的联网设备越来越多,如电视、播放机、文件服务器、打印机、笔记本、手机等等,直接用IP地址的方式来管理这些设备越来越困难,费时费力。自己可以建一个hosts文件,为每一台设备取一个名字,并分配一个固定的IP地址。 示例如下。 hosts文件: 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback 192.168.*.250 DL #PRE #PC机(DL) 192.168.*.251 R478 #PRE #TL-R478+路由器 校园网 192.168.*.252 R300 #PRE #MW300R路由器 192.168.*.253 4K #PRE #PC机(4K) 192.168.*.230 TV #PRE #电视 192.168.*.231 Z9F #PRE #音响 192.168.*.232 BD #PRE #播放机 192.168.*.1 AC5300 #PRE #主路由器 192.168.*.2 H3C #PRE #交换机 192.168.0.1 EPON #PRE #电信光猫 ……
hosts文件,你可以存到本机里面,如C:\Windows\System32\drivers\etc目录下。 这样做有两个问题。一是Android手机是不允许写入hosts文件的。二是在数十台设备维护hosts的数十个版本是不可行的。 一个办法是把hosts文件写到路由器里面。如 /tmp/etc/hosts 但是!但是!但是!重要的事情说三边,华硕路由器在重新启动后,任何对hosts文件的更改都会被清除,重置为路由器系统默认的hosts文件。
能否把hosts文件存到路由器挂载的U盘中,如 /tmp/mnt/sda1/asusware.arm/etc/init.d目录下,等路由器启动后自动将 /tmp/mnt/sda1/asusware.arm/etc/init.d/hosts复制到/tmp/etc/hosts, 实现hosts文件的更新呢?并让hosts文件生效呢?
答案至少有三种。 试验表明,现在能用的是第三种。请看下文!
二、以Sxxhosts命名的脚本实现启动时自动执行 (1)编写一个脚本:S50hosts,文件名以大写S开头+xx两位数字+任意名字。 (2)将脚本放到/opt/etc/init.d/ S50hosts S50hosts脚本如下: #!/bin/sh #确保脚本第一行内容为#!/bin/sh,并且以 UNIX 作为换行符 #等待路由器所有程序初始化完成,不断查询程序是否初始化完成 i=0 while [ $i -le 20 ]; do success_start_service=`nvram get success_start_service` if [ "$success_start_service" == "1" ]; then break fi i=$(($i+1)) echo "autorun APP: wait $i seconds..."; sleep 1 done #复制自己定义的hosts文件到/etc目录下 cp /opt/etc/init.d/hosts /tmp/etc/hosts
#复制域名解析配置文件resolv.conf到/tmp及/tmp/etc目录下 cp /opt/etc/init.d/resolv.conf /tmp/etc/resolv.conf cp /opt/etc/init.d/resolv.conf /tmp/resolv.conf
#复制dnamasq配置文件dnsmasq.conf到/tmp/etc目录下 cp /opt/etc/init.d/dnsmasq.conf /tmp/etc/dnsmasq.conf
#复制dnamasq配置文件dnsmasq.conf到/tmp目录下 cp /opt/etc/init.d/resolv.dnsmasq/tmp/resolv.dnsmasq
sleep 20 #非常重要:重启 dnsmasq,并使hosts文件生效 #dnsmasq是华硕路由器自带的一个轻量DNS解析服务,首先查询/etc/hosts文件, #查不到的话,查询上有DNS服务器,如中国电信成都的DNS服务器:61.139.2.69 # service restart_dnsmasq执行后会导致 hosts 同开机一样被清空 #正确的操作方式如下 killall -SIGHUP dnsmasq
特别提示: (1)手动执行脚本 ./S50hots,dnsmasq 重启成功,自定义hosts生效。 (2)重新启动路由器,S50hots脚本并未自动执行。
目标没有达成! 可能原因是华硕路由器的新版本固件不再支持这种脚本自动执行方法。 为了实现我们的目标:开机自动执行S50hosts这个脚本,需要找另外的新方法。
三、jffs2_exec=””指定脚本执行 华硕路由器JFFS分区是路由器闪存的可写部分,是放置脚本文件的好地方,因为此分区在路由器重新启动后不会被擦除,继续有效。放在此分区的脚本将在启动时先于USB磁盘被加载,对于要在路由器关机后不丢失脚本的需求,可以使用路由器JFFS分区。 JFFS分区原本用于存储路由器的所有配置信息,使用nvram show命令可以查看所有配置参数。
华硕路由器开机时,有一个脚本自动运行的钩子: nvram set jffs2_on=1 nvram set jffs2_exec=”sh /jffs/init.sh” 以上命令指定路由器启动时,自动运行 /jffs/init.sh脚本。
nvram show|grepjffs2_ 命令查看JFFS分区启动自动执行脚本的设置如下: jffs2_enable=1 jffs2_exec=sh/jffs/init.sh jffs2_format=0 jffs2_on=1 jffs2_size=66060288
init.sh脚本文件 #!/bin/sh # # init.sh - custom script executed at boot(during start of jffs) # # Note: # 1) NVRAM variable "jffs2_exec" must point to this script # nvram set jffs2_exec="sh /jffs/init.sh" # 2) The calling code waits for this script to terminate, # so in order to not stall the boot process, we quickly # move to the background # the calling code waits for the script toterminate (different from script_usbmount), # so as the script waits for routerservices to finish start-up # (polling success_start_service NVRAMvariable), # the script should move to background in apseudo-daemon way.
maxwait=300 #设置调用/opt/etc/init.d/S50hosts脚本的变量 S50hosts='/opt/etc/init.d/S50hosts' umask 022 # # move to background in a subshell # ( cd / #ignore SIGHUP trap '' SIGHUP #redirect STDIN, STDOUT, STDERR exec 0< '/dev/null' exec 1> '/dev/null' exec 2> '/dev/null' # #wait till all the system services are started #by polling "success_start_service" NVRAM variable # i=0 while [ "$i" -le "$maxwait" ] do success_start_service="$( nvram get 'success_start_service' )" if [ "$success_start_service" == '1' ] then break fi sleep 10 i=$(( $i + 10 )) done if [ "$i" -gt "$maxwait" ] then # timeout logger 'init.sh script: timout waiting for"success_start_service"' exit 1 fi # #wait a little longer to allow ntp client to get correct time # sleep 60 logger 'init.sh executing' #append custom hosts file to hosts if [ -x "$S50hosts" ] then #调用S50hosts脚本 eval "$S50hosts" fi #add other stuff you want to do... echo "S50hosts done!">>/jffs/init.log exit 0 )& exit 0
特别提醒: (1) 手动执行/jffs/init.sh,S50hosts脚本成功执行,hosts生效。 (2) 遗憾的是,华硕路由器重新启动时,/jffs/init.sh并未自动执行。 这意味着用 jffs2_exec=”sh /jffs/init.sh” 这一钩子自动执行脚本的努力化为泡影! 也就是说华硕路由器不在支持这一机制。
为了实现我们的目标:开机自动执行S50hosts这个脚本,需要再度寻找新的方法!
四、script_usbmount=“”指定脚本执行
除上述jffs2_exec=”sh /jffs/init.sh” 这一钩子之外,华硕路由器理论上还有可用的钩子: 挂载USB和卸载USB设备时的钩子,分别是script_usbmount,script_usbumount。
使用nvram set script_usbmount=”sh /jffs/init.sh”命令设置USB挂载时执行的脚本/jffs/init.sh。
*重启路由器!
幸运的是/jffs/init.sh得以自动运行。
其效果是:存在U盘上的S50hosts脚本得以执行,并且hosts即时生效。
五、小结 华硕路由器启动时自动执行脚本的机制至少有: (1)以Sxxhosts命名的脚本实现启动时自动执行; (2)jffs2_exec=””指定脚本执行; (3)script_usbmount=“”指定脚本执行
随着时间的推移,前两种机制已经作废! 幸运的是script_usbmount=“”指定脚本执行这一机制目前还有效。
-完-
|