Açıklama Yok

Dew-OF-Aurora 9433fbf787 fix: some bugs 1 hafta önce
scripts 9433fbf787 fix: some bugs 1 hafta önce
substore eda833bb2d fix: bug 3 hafta önce
.gitignore 808a6cf1b1 fix: for KV 1 ay önce
CLAUDE.md 1f3445b644 feature: add time interval 2 hafta önce
README.md bd94b2646b fix: bug 2 hafta önce
build_router_package.sh 877831cbe9 fix: bug feat: substorejs different mode 1 ay önce
config.local.json 808a6cf1b1 fix: for KV 1 ay önce
config.server.json 9433fbf787 fix: some bugs 1 hafta önce
config_router.conf 944f6f5dd1 fix: server interval to 30 min 3 hafta önce
workflow.md 9433fbf787 fix: some bugs 1 hafta önce

README.md

vmess-domain-rotator

用于选择优选目标并产出运行时文件,支持三种模式:

  • 服务器模式(API -> 域名,支持自动提交 runtime-state
  • 本地 Python cfst 模式(本机 cfst -> IP)
  • BusyBox 路由器模式(路由器 sh + cfst -> IP + HTTP 暴露)

1. 目录与入口

核心脚本:

  • scripts/domain_updater.py:Python 主入口(api / cfst_local
  • scripts/run_update_and_commit.sh:服务器模式调度入口(含 git 同步)
  • scripts/install_debian.sh / scripts/uninstall_debian.sh:systemd 安装/卸载
  • scripts/router_local_update.sh:路由器更新入口(BusyBox sh
  • scripts/router_local_http.sh:路由器 HTTP 入口(BusyBox httpd
  • build_router_package.sh:路由器部署包打包脚本(生成 vmess.tar.gz

配置文件:

  • config.server.json:服务器模式
  • config.local.json:本地 Python cfst 模式
  • config_router.conf:BusyBox 路由器模式

config.json / config.example.json 已废弃。


2. 输出文件约定

三种模式都围绕同类输出:

  • 文本值文件:当前选中值
  • JSON 文件:当前状态与候选信息
  • state 文件:上次可用值(fallback)
  • export vars 文件:给外部系统消费

默认目录:

  • 服务器模式:runtime/
  • 路由器相关模式:cfip_runtime/

state.jsonsubstore_vars.json 用途:

  • state.json:持久化上次可用值(如 last_good_domain / last_good_ip),用于失败时 fallback。
  • substore_vars.json:给下游(如 Sub-Store)提供轻量变量(当前值、UPDATED_ATSTATUS),避免解析完整 runtime JSON。

top_candidates 字段规则(API / CFST):

  • 仅保留语义重合或通用字段,字段名统一(如 domainiploss_rateavg_latencydownload_speedregion)。
  • 改为“有值才输出该字段”,没有值不再写空字符串/空数组/null 占位。
  • API 评分相关字段(如 score_valuescorescreated_raw)仅在有值时输出。

3. 服务器模式(API)

3.1 适用场景

  • python3
  • 可访问目标 API
  • 需要自动提交到 runtime-state

3.2 快速执行

python3 scripts/domain_updater.py --config config.server.json
bash scripts/run_update_and_commit.sh config.server.json

强制提交:

bash scripts/run_update_and_commit.sh --force-commit config.server.json
# 或
GIT_FORCE_COMMIT=1 bash scripts/run_update_and_commit.sh config.server.json

3.3 安装与部署(Debian/Ubuntu systemd)

为了在服务器上实现无人值守的定时域名更新与自动 Git 提交,本项目提供了一套完整的 systemd 服务安装脚本。

3.3.1 系统准备与要求

  • 操作系统:Debian / Ubuntu / Armbian 等基于 Debian 的发行版。
  • 系统工具systemd(系统服务管理)、runuser(安全切换用户执行)。
  • 软件依赖:Python 3、Git、ca-certificates(若缺失,安装脚本默认会通过 apt-get 自动补全)。

3.3.2 安装脚本参数详解

你可以使用 sudo bash scripts/install_debian.sh [options] 进行灵活安装:

参数选项 默认值 说明
--config <path> config.server.json 配置文件路径(若为相对路径,则相对于仓库根目录)
--interval <value> 30min --offpeak-interval 的别名(定时器默认/非高峰间隔)
--peak-start <hour> 19 高峰时段的起始小时数,取值范围 0-23(如 19 代表 19:00)
--peak-end <hour> 24 高峰时段的截止小时数,取值范围 1-24(如 24 代表 24:00,均会被自动规范化为 0)
--peak-tz <timezone> Asia/Shanghai 高峰时段判定的参考时区
--peak-interval <value> 10min 高峰时段的域名更新间隔,如 5min10m
--offpeak-interval <value> 30min 非高峰时段的域名更新间隔,如 30min1h
--user <name> 当前 sudo 用户 运行 systemd 服务的非 root 系统用户
--group <name> 当前 sudo 用户组 运行 systemd 服务的系统用户组
--git-push <0\|1> 1 选出新域名并 commit 后,是否自动推送(git push)到远程仓库
--git-push-remote <name> origin 推送的 Git 远程仓库名称
--git-http-username <u> git 远程 Git 仓库的 HTTPS 认证用户名
--git-http-token <token> 远程 Git 仓库的 HTTPS 访问令牌(用于非交互式免密推送)
--git-http-token-file <path> 从指定文件中读取 HTTPS 访问令牌,避免命令行泄露敏感信息
--git-use-credential-store <0\|1> 1 是否使用 Git 凭据辅助存储(credential.helper store)持久化 Token
--git-credentials-file <path> 自定义凭据存储文件的路径(若不指定,默认保存在服务用户家目录下)
--no-install-deps 跳过 apt-get 依赖包检测与自动安装
-h, --help - 显示帮助信息

[!IMPORTANT] 关于 Git 自动推送(Push)与凭据认证

  1. HTTPS 认证(推荐使用 Token):指定 --git-http-token--git-http-token-file。安装脚本会自动启动 git credential approve 为指定的运行用户配置全局凭据,且所有 Token 信息都会以安全权限(600)保存在独立配置文件中,杜绝安全隐患。
  2. SSH 认证:如果远程仓库使用 SSH 地址(例如 git@github.com:...),只需在安装时指定 --git-use-credential-store 0。只要确保配置的 --user 用户的 SSH 密钥已被授权到远程 Git 平台即可。
  3. 安全隔离:服务不允许以 root 用户身份保存 Git Token。若使用 Token 认证,必须指定非 root 用户(默认即为执行 sudo 的普通用户)。
  4. Git 安全目录:安装脚本会自动为服务运行用户注入 git config --global --add safe.directory 配置,彻底避免 systemd 执行时因目录所有权引起的 Git 安全阻拦错误。

3.3.3 快速安装示例

示例 1:最简安装(每 30 分钟自动运行,使用默认配置,支持 Git 推送)

sudo bash scripts/install_debian.sh

示例 2:自定义时间间隔,并通过文件安全读取 GitHub/GitLab 访问令牌

sudo bash scripts/install_debian.sh --interval 10min --git-http-username aurora --git-http-token-file /home/aurora/.github_token

示例 3:纯本地运行,不推送到远程仓库

sudo bash scripts/install_debian.sh --git-push 0

3.4 卸载服务

如果你需要卸载 systemd 定时任务和服务,可以使用自带的卸载脚本。该脚本会自动停止正在运行的定时器与服务,移除系统 unit 文件,清理 Git 全局安全路径配置,并重载 systemd

sudo bash scripts/uninstall_debian.sh [options]

参数选项:

  • --keep-auth-files:保留安装时生成的环境配置文件(/etc/vmess-domain-rotator.env)与保存凭据的安全目录(/var/lib/vmess-domain-rotator)。若计划稍后重新安装,建议加上此参数。
  • --service-name <name>:指定要卸载的服务基名(默认为 vmess-domain-rotator)。

快速卸载示例:

# 彻底卸载(默认清除所有关联的 Token 与配置文件,保留 git 仓库代码)
sudo bash scripts/uninstall_debian.sh

# 卸载服务但保留认证凭据
sudo bash scripts/uninstall_debian.sh --keep-auth-files

3.5 常用命令与日常维护

部署完成后,你可以通过以下命令对服务进行管理和排错:

# 查看定时器状态与下一次执行时间
sudo systemctl status vmess-domain-rotator.timer

# 查看单次服务运行状态与退出码
sudo systemctl status vmess-domain-rotator.service

# 手动立即触发一次更新(无需等待定时器,方便测试)
sudo systemctl start vmess-domain-rotator.service

# 实时查看运行日志(包含定时任务与手动执行日志,推荐)
sudo journalctl -t vmess-domain-rotator -f --no-pager

# 仅查看定时任务服务的运行日志
sudo journalctl -u vmess-domain-rotator.service -f --no-pager

# 查看服务最近 100 行日志
sudo journalctl -u vmess-domain-rotator.service -n 100 --no-pager

# 语法与配置预检
env PYTHONPYCACHEPREFIX=/tmp/pycache python3 -m py_compile scripts/domain_updater.py
bash -n scripts/run_update_and_commit.sh

# 检查当前配置解析出的实际输出路径
python3 scripts/domain_updater.py --config config.server.json --print-output-settings

# 手动强制提交当前域名(即便域名没有发生变化,也会生成 commit 并推送到 remote)
sudo -u aurora bash scripts/run_update_and_commit.sh --force-commit config.server.json

3.6 核心规则:筛选与评分策略

服务器模式(API)采用结构化的过滤与权衡评分机制,保证筛选出的域名兼顾极低的延迟极低的丢包率

3.6.1 API 字段转换映射 (record_mapping)

通过 config.server.json 中的 record_mapping 块,可以将任意 API 响应中的自定义字段映射为标准字段。目前已映射的标准字段包括:

  • domain:物理域名/IP。
  • created_at:记录创建时间(支持时区与多种格式解析)。
  • yd_latency / yd_pkg_lost_rate:移动延迟 / 移动丢包率。
  • dx_latency / dx_pkg_lost_rate:电信延迟 / 电信丢包率。
  • lt_latency / lt_pkg_lost_rate:联通延迟 / 联通丢包率。
  • avg_latency / avg_pkg_lost_rate:三网平均延迟 / 平均丢包率。

3.6.2 数据筛选过滤器 (record_filterdomain_filter)

  • API 记录过滤 (record_filter):在解析前排除包含特定语义的字段。例如,默认过滤掉 host_provider 为 "CF优选IP" 的记录,或排除特定敏感域名。
  • 域名规则过滤 (domain_filter):根据正则表达式排除不合格的物理格式。例如,默认使用正则排除直接为 IPv4 格式的记录,只保留纯域名。

3.6.3 评分排序策略 (scoring)

评分机制(以 weighted_average 策略为例)将对剩余的候选域名进行加权评分:

  • 加权字段设置 (weighted_fields): 在默认的 config.server.json 中,为了优化中国移动线路的访问表现,配置了以下加权项:
    • yd_latency (权重: 1.0)
    • yd_pkg_lost_rate (权重: 10.0)
  • 评分计算方式: $$\text{Score} = \frac{\sum (\text{Field Value} \times \text{Weight})}{\sum \text{Weights}}$$
  • 优先级方向 (prefer_lower):设置为 true,分值越低(延迟越低、丢包率越少)则排名越靠前。
  • 时效性过滤 (within_hours):自动过滤掉创建时间超过 24 小时的陈旧测试记录(服务器模式当前设为 0 以禁用该前置过滤)。
  • 决胜规则 (tie_breakers):当加权评分(对比 yd_latencyyd_pkg_lost_rate)相同时,支持按备用字段进行依次决胜排序。默认首先选择 avg_latency(三网平均延迟)最低的候选域名;若仍相同,则依次按 created_at 降序、domain 升序规则决胜,保证排序的绝对确定性。

3.6.4 备用容灾设计(Fallback)

如果 API 请求超时、解析失败或过滤后无可用域名:

  1. 更新器会读取 runtime/state.json 中上一次持久化保存的 last_good_domain
  2. 自动降级回退使用该域名,确保下游服务不会因为短暂的网络扰动而中断。
  3. 状态标记为 error_use_last_good,调度脚本捕获后会以 chore(fallback): 作为前缀提交,方便管理员追溯。

3.7 日志格式(服务器模式)

scripts/run_update_and_commit.shscripts/install_debian.shscripts/uninstall_debian.sh 的日志统一为:

[YYYY-MM-DD HH:MM:SS] [vmess-domain-rotator] <message>

Git 提交信息中也会带 UTC 时间戳,例如:

chore: rotate preferred value to example.com (2026-05-11T13:03:16Z)
chore(fallback): rotate preferred value to example.com (2026-05-11T13:03:16Z)

chore(fallback) 表示源端出错、使用了上次的可用值。

3.7.1 手动执行日志重定向 (journald tee)

当你在控制台手动执行 scripts/run_update_and_commit.sh(非 systemd 服务直接运行)时,为了确保调试时的所见所得与运维的日志可追溯性,脚本内置了 journald tee 日志重定向功能:

  • 脚本检测到环境变量 INVOCATION_ID 为空且系统安装有 systemd-cat 时,会自动通过管道进行双流输出重定向。
  • 所见即所得:终端内仍会显示常规的标准输出(stdout)与标准错误(stderr),方便交互式调试与结果观测。
  • 系统级追溯:输出的副本会被自动发送给 systemd-journald 守护进程,并打上 vmess-domain-rotator 的 Syslog Identifier 标签。
  • 可以使用 journalctl -t vmess-domain-rotator -f 命令将定时任务与手动调试的日志归于同一时间线混合排查。

3.8 高峰期/非高峰期双频自适应调度策略

项目提供了非常灵活的高峰期(Peak Hour)与非高峰期(Off-Peak Hour)双频自适应调度机制。此设计能够使系统在晚高峰期间高频运行测速或更新以保证代理域名的实时可用,并在低谷期间自动降低频率以降低对第三方 API 及网络资源的开销。

3.8.1 定时器最小周期驱动

  • install_debian.sh 安装脚本在部署时,会自动读取 --peak-interval(高峰间隔,默认 10min)与 --offpeak-interval(非高峰间隔,默认 30min)。
  • 脚本通过 to_minutes 函数将其统一解析为分钟数,并取两者的最小值(通常为高峰期的时间间隔)作为 systemd timer 定时的基础触发周期: $$\text{TIMER_INTERVAL} = \min(\text{Peak Interval}, \text{Off-Peak Interval})$$
  • 也就是说,系统底层的定时器会以最高频的节奏(如每 10 分钟一次)醒来并启动 run_update_and_commit.sh 脚本。

3.8.2 脚本自适应判定与容差跳过

每次脚本被唤醒时,会判断当前时间是否处于高峰期:

  1. 时区一致性:通过 TZ="Asia/Shanghai" date (时区可配置)跨命令强制时区覆盖,即便服务器处于 UTC 时区或海外机房,也能精准在北京时间高峰段(默认 19:00 - 24:00)运行。
  2. 跨零点支持:判断支持跨越午夜的区间定义(例如 peak_start=22, peak_end=2 代表晚上十点到凌晨两点)。
  3. 高峰期行为:如果属于高峰期,直接放行,每次触发均会完整执行后续的 Python 优选与 Git 同步(10 分钟更新一次)。
  4. 非高峰期判定(容差对齐): 如果属于非高峰时段,脚本只应在长周期边界(如 30 分钟边界,即 0 分或 30 分)执行更新。 为了防止由于系统调度微小漂移(例如定时器在 29m 58s30m 02s 唤醒脚本)导致漏判,脚本设计了容差窗口(Tolerance Window)判定
    • 容差窗口大小定为高峰周期的二分之一左右: $$\text{Tolerance} = \frac{\text{Peak Interval} + 1}{2}$$
    • 脚本计算当前分钟数对非高峰间隔的余数: $$\text{Remainder} = \text{Current Minute} \pmod{\text{Off-Peak Interval}}$$
    • 如果余数超出容差区间,代表这是一次中间的冗余唤醒(如第 10 分钟或第 20 分钟),脚本将记录 off-peak run skipped 日志并安全退出 0;否则(如第 29 分钟或第 0 分钟)进行放行(30 分钟更新一次)。

4. 本地 Python cfst 模式

4.1 适用场景

  • python3
  • 本机可执行 cfst
  • 不需要 BusyBox 专用脚本

4.2 快速执行

python3 scripts/domain_updater.py --config config.local.json

默认配置当前指向:

  • cfst_local.work_dir = ./cfst_darwin_arm64(macOS ARM;部署时按实际平台修改,如 ./cfst_linux_armv5
  • cfst_local.binary = ./cfst
  • 输出目录以 config.local.json -> output.runtime_dir 为准(当前仓库默认 ./runtime

4.3 维护命令

# 输出文件检查(按当前 config.local.json 默认 runtime_dir=./runtime)
cat runtime/current_ip.txt
cat runtime/current_ip.json
cat runtime/state.json
cat runtime/substore_vars.json

# 仅检查输出路径解析
python3 scripts/domain_updater.py --config config.local.json --print-output-settings

5. BusyBox 路由器模式

5.1 适用场景

  • 路由器没有 Python
  • 有匹配架构的 cfst
  • 有完整 BusyBox(需要 httpd applet)

5.2 推荐目录(ASUS RT-AC68U 示例)

/jffs/vmess/
├── busybox_armv7l
├── config_router.conf
├── scripts/
│   ├── router_local_update.sh
│   └── router_local_http.sh
└── cfst/
    ├── cfst
    ├── ip.txt
    └── result.csv

5.3 关键配置(config_router.conf

  • CFST_WORK_DIR / CFST_BIN / CFST_RESULT_FILE
  • CFST_SPEED_LIMIT(建议设置,如 5
  • RUNTIME_DIR / VALUE_TEXT_FILE / VALUE_JSON_FILE
  • BUSYBOX_BIN(如 ./busybox_armv7l
  • HTTP_PORT(默认 8080

5.4 手动执行

cd /jffs/vmess
sh scripts/router_local_update.sh config_router.conf
sh scripts/router_local_http.sh config_router.conf

说明:

  • 手动终端执行 update 时会显示 cfst 原始输出(便于排错)
  • 重定向日志/后台执行时默认静默 cfst,只保留 [router-local] 摘要
  • HTTP 脚本只使用 BUSYBOX_BIN 指向的 BusyBox httpd,不使用 ASUS 系统 httpd

5.5 自启动(/jffs/scripts/services-start

VMESS_DIR="/jffs/vmess"
CONFIG="./config_router.conf"
UPDATE_LOG="/tmp/router_local_update.log"
HTTP_LOG="/tmp/router_http.log"
HTTP_PROCESS_PATTERN='[r]outer_local_http.sh'

start_vmess_http() {
  if ps | grep -q "$HTTP_PROCESS_PATTERN"; then
    return 0
  fi
  cd "$VMESS_DIR" || exit 1
  nohup sh scripts/router_local_http.sh "$CONFIG" >> "$HTTP_LOG" 2>&1 &
}

cd "$VMESS_DIR" || exit 1

# 避免开机过早导致 result.csv 为空
sleep 60
i=1
while [ "$i" -le 5 ]; do
  if sh scripts/router_local_update.sh "$CONFIG" >> "$UPDATE_LOG" 2>&1; then
    break
  fi
  sleep 20
  i=$((i + 1))
done

cru d vmess_rotate
cru a vmess_rotate "0 */12 * * * cd $VMESS_DIR && sh scripts/router_local_update.sh $CONFIG >> $UPDATE_LOG 2>&1"

sleep 10
start_vmess_http

cru d vmess_watchdog
cru a vmess_watchdog "*/5 * * * * if ! ps | grep -q '$HTTP_PROCESS_PATTERN'; then cd $VMESS_DIR && nohup sh scripts/router_local_http.sh $CONFIG >> $HTTP_LOG 2>&1 & fi"

5.6 维护命令

# 基础检查
cd /jffs/vmess
chmod +x busybox_armv7l
./busybox_armv7l --list | grep '^httpd$'

# 更新与结果检查
sh scripts/router_local_update.sh ./config_router.conf
cat cfip_runtime/current_ip.txt
cat cfip_runtime/current_ip.json
cat cfip_runtime/state.json

# HTTP 与端口检查
sh scripts/router_local_http.sh ./config_router.conf
ps | grep router_local_http.sh
netstat -lntp | grep ':8080'
curl http://127.0.0.1:8080/current_ip.txt

# 常见端口冲突处理(Address already in use)
# 1) 改 config_router.conf 的 HTTP_PORT
# 2) 或停止旧进程后重启

5.7 日志格式(路由器模式)

scripts/router_local_update.shscripts/router_local_http.sh 的日志统一为:

[YYYY-MM-DD HH:MM:SS] [router-local|router-http] <message>

5.8 [最佳实践] 延长路由器闪存寿命(防擦写优化)

[!WARNING] 为什么要配置防擦写优化? 路由器的 /jffs 目录是位于 NAND/NOR Flash 物理闪存介质上的。本项目默认每 12 小时执行一次本地 cfst 测速并生成 result.csv。如果将这些临时文件直接写入 /jffs长期高频擦写将严重缩短路由器硬件闪存的寿命

本项目已经完美支持了绝对路径智能解析与动静分离存储方案。你可以将所有高频读写的临时文件和运行期数据全部重定向至系统的 RAM 内存临时文件系统(/tmp,而仅将最关键的初始化与容灾文件(state.json)保存在闪存上。

5.8.1 防擦写推荐配置

修改路由器上的 config_router.conf,将高频写操作的目录与文件路径配置如下:

# 1. 测速工作区与输入文件保存在 flash 上(只读性质)
CFST_WORK_DIR="/jffs/vmess/cfst"
CFST_BIN="./cfst"
CFST_IP_FILE="ip.txt"

# 2. 【核心优化】测速输出 csv 定向到内存系统(/tmp),不磨损硬件!
CFST_RESULT_FILE="/tmp/vmess_result.csv"

# 3. 【核心优化】运行期数据目录全部指向内存,速度飞快且零硬件磨损
RUNTIME_DIR="/tmp/vmess_runtime"
VALUE_TEXT_FILE="current_ip.txt"
VALUE_JSON_FILE="current_ip.json"
EXPORT_VARS_FILE="substore_vars.json"

# 4. 【容灾持久化】将上次可用值 state.json 独立保存在物理闪存中,保证重启后不丢失
# 因为只有在真正检测到 IP 变化并写入成功时才会写一次 Flash,写入频率极低(通常几天或几周写一次),安全无虞。
STATE_FILE="/jffs/vmess/state.json"

5.8.2 原理解析与效果

  1. 自动建目录:在 RAM 中,/tmp/vmess_runtime 会在每次开机或定时器运行 router_local_update.sh 时,通过 mkdir -p 自动创建,无需手动干预。
  2. 零闪存磨损:在测速时,cfst 会将大量的下载速度数据、中间进度及最终的 vmess_result.csv 写入 RAM 内存,彻底消除闪存介质每 12 小时擦写几百 KB 的问题。
  3. 极速读取:BusyBox httpd 将直接挂载 /tmp/vmess_runtime 目录来服务 Sub-Store。因为数据常驻内存,HTTP 响应速度可以提升至微秒级。
  4. 断电容灾存留:如果路由器断电重启,内存中的 /tmp 随之清空。但由于我们把备用状态 state.json 单独放回了物理闪存 /jffs/vmess/state.json,下一次定时器启动时,如果暂时无法连接网络或测速报错,脚本依然能成功从 Flash 读回上次可用的 fallback IP 并完美恢复服务。

6. Sub-Store 脚本模式说明

substore/operator_template.js 支持:

  • VALUE_SOURCE_MODE = "default":路由器优先,低速时切服务器
  • VALUE_SOURCE_MODE = "server_only":只用服务器
  • VALUE_SOURCE_MODE = "router_only":只用路由器

速度阈值使用 MB/s

  • ROUTER_MIN_SPEED_MB_PER_S = 5
  • download_speed 纯数字按 MB/s 解释

缓存按 VALUE_SOURCE_MODE 隔离,切换模式后不会命中旧缓存。


7. 路由器部署包打包

./build_router_package.sh

可选覆盖:

BUSYBOX_SRC="/path/to/busybox_armv7l" \
CFST_SRC_DIR="/path/to/cfst_dir" \
OUT_TAR="/path/to/vmess.tar.gz" \
./build_router_package.sh

打包内容默认为:

  • vmess/busybox_armv7l
  • vmess/config_router.conf
  • vmess/scripts/router_local_update.sh
  • vmess/scripts/router_local_http.sh
  • vmess/cfst/*

8. 注意事项

  1. 三种模式的配置不要混用。
  2. 只有服务器模式默认做 git 自动提交。
  3. state.json 需持久化,否则 fallback 不可用。
  4. 路由器模式请优先使用完整 BusyBox httpd,不要依赖系统精简 httpd / nc
  5. 卸载脚本会自动清理对应服务用户的 git safe.directory 配置。