真机实测(0.8.47,2026-11-06)定位到的根因不是「没有 NTP 客户端」: 固件自带 ntp-4.2.8p14(/usr/sbin/ntpd)和 /etc/ntp.conf(4 个 pool.ntp.org), 但没有任何 init 脚本/进程启动它 —— 有客户端、没启动。 实测证据: - RTC 存在且可读(/dev/rtc0,10003000.rtc),内核开机 hctosys=1, 冷启动不回到 1970 → 掉电保持;RTC 存 UTC(since_epoch == date +%s)。 - 但 RTC 会走慢且无人纠正:实测系统时间比 NTP 慢 49 s;把系统时间人为 拨错 4 h 后观察 65 s 无人纠正,RTC 也不跟随系统时间。 - UDP/123 出网正常(ntpd -q 一次成功 time set +48.877s);DNS/HTTP 正常。 - udhcpc 的 default.script 不处理 option 42,实测热点也不下发。 - ntpd -q 不会回写 RTC(步进后 sys-rtc 仍差 49 s)→ 必须 hwclock -w -u。 - ntpd 没有超时参数,无服务器时永久存活 → 必须自带看门狗。 - -p 形式的 server 首个 poll 要 ~64 s;配置里加 iburst 后 8 s 内返回。 实现(新增,不改任何基线文件): - /usr/bin/meow_ntpsync:一次性校时器。复用 ntpd -q -g + 运行时生成的 iburst 配置;内置 IP 兜底(阿里/腾讯/Cloudflare)→ DNS 名兜底; 单次 15 s 看门狗、默认路由轮询、1 h 短路、进程锁、失败静默。 成功严格校时后 hwclock -w -u 回写 RTC(RTC 存 UTC,必须 -u)。 - /etc/init.d/S45meow_ntpsync:开机只 setsid 后台拉起并立即返回 (关键路径 +0 秒;后台最长约 150 s 自行退出),失败不阻断 init。 - /usr/share/udhcpc/default.script.d/50meow_ntpsync:只在 bound/renew 触发(设备上唯一可靠的「网络就绪」事件),后台拉起后立即 exit 0; 有 $ntpsrv(option 42)就优先用。基线 default.script 本就有 HOOK_DIR 循环,目录原本为空。 - tests/run_tests.sh:宿主沙箱单测(假 ntpd/hwclock/网络探测)。 验证:dash 与 busybox sh 各 sh -n 通过;单测两套 shell 各 23/23 通过; 真机(/tmp 下运行,未装系统目录)首跑 8 s rc=0、ntpd slew 成功、 RTC 由 1793940395 写成 1793940452(49 s 偏差被纠正)、hwclock -u -r 吻合; 二次运行 0 s 短路;-b -t 3 无网络 5 s 退出 rc=1; DHCP 灌入不可达服务器 192.0.2.x 仍靠 IP 兜底在 ~10 s 内成功。
41 lines
1.2 KiB
Bash
Executable File
41 lines
1.2 KiB
Bash
Executable File
#!/bin/sh
|
||
#
|
||
# S45meow_ntpsync — 开机网络校时(M22)
|
||
#
|
||
# 只负责把同步器丢到后台并**立即返回**,开机关键路径增加 0 秒。
|
||
# 真正的「等网络就绪 + 有限重试 + 总超时」全在 /usr/bin/meow_ntpsync 里。
|
||
#
|
||
# 为什么排 S45:S40network 只 ifup 了 lo,WiFi 由 S43 之后才起来,租约更晚,
|
||
# 所以本脚本启动时大概率还没有网络——同步器自己轮询默认路由(最多 -t 秒)。
|
||
# WiFi 在更晚(用户手动连)才就绪的情况,由 udhcpc 钩子
|
||
# /usr/share/udhcpc/default.script.d/50meow_ntpsync 在拿到租约时再触发一次。
|
||
#
|
||
# 失败不阻断 init:所有分支都 exit 0(除非参数错误)。
|
||
#
|
||
case "$1" in
|
||
start)
|
||
printf "Starting meow_ntpsync: "
|
||
[ -x /usr/bin/meow_ntpsync ] || { echo "SKIP (not installed)"; exit 0; }
|
||
setsid /usr/bin/meow_ntpsync -b -t 120 >/dev/null 2>&1 &
|
||
echo "OK"
|
||
;;
|
||
stop)
|
||
printf "Stopping meow_ntpsync: "
|
||
if [ -f /tmp/meow_ntpsync.lock/pid ]; then
|
||
kill "$(cat /tmp/meow_ntpsync.lock/pid 2>/dev/null)" 2>/dev/null
|
||
fi
|
||
rm -rf /tmp/meow_ntpsync.lock 2>/dev/null
|
||
echo "OK"
|
||
;;
|
||
restart|reload)
|
||
"$0" stop
|
||
"$0" start
|
||
;;
|
||
*)
|
||
echo "Usage: $0 {start|stop|restart}"
|
||
exit 1
|
||
;;
|
||
esac
|
||
|
||
exit 0
|