설명 없음

Dew-OF-Aurora 9b9a0165ca opt: for json field 2 주 전
runtime 9b9a0165ca opt: for json field 2 주 전
scripts 9b9a0165ca opt: for json field 2 주 전
substore 19e1ce59c9 change: submit to runtime-state 3 주 전
CLAUDE.md 9b9a0165ca opt: for json field 2 주 전
README.md 9b9a0165ca opt: for json field 2 주 전
config.example.json 9b9a0165ca opt: for json field 2 주 전
config.json 9b9a0165ca opt: for json field 2 주 전
workflow.md 9b9a0165ca opt: for json field 2 주 전

README.md

vmess-domain-rotator

一个用于 自动获取优选域名、写入 runtime/ 运行时文件,并按计划将运行时变更提交到 runtime-state 分支的工具。


1. 功能概览

本项目主要完成以下流程:

  1. 从 API 拉取候选域名/IP
  2. 解析并过滤候选结果
  3. 按规则打分/选择最终域名
  4. 写入运行时文件到 runtime/
  5. (可选)将运行时变更自动提交并 push 到 runtime-state

核心脚本:

  • scripts/domain_updater.py:执行域名拉取、选择与写文件
  • scripts/run_update_and_commit.sh:执行 updater + git 提交/推送
  • scripts/install_debian.sh:Debian 下安装 systemd service + timer
  • scripts/uninstall_debian.sh:卸载 systemd 与认证环境文件

2. 运行产物

默认写入仓库根目录 runtime/

  • runtime/current_domain.txt:当前域名(纯文本)
  • runtime/current_domain.json:当前结果 JSON
  • runtime/state.json:状态文件(含 last_good_domain
  • runtime/substore_vars.json:给外部系统消费的变量

注意:domain_updater.py 现在会按 --config 文件所在目录解析 output.runtime_dir(默认 ./runtime),避免误写到 scripts/runtime/


3. 本地快速开始

3.1 配置

编辑 config.json(可先从 config.example.json 复制一份再按你的 API 调整)。

典型解析路径(如 API 返回 data.good[].ip):

"parser": {
  "field_paths": ["data.good[].ip"],
  "json_paths": [],
  "regex": "[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"
}

3.2 配置块说明(API 无关)

你可以为不同 API 使用同一套脚本,只调整配置:

  • api:请求地址、方法、header、query 参数、超时
  • parser:如何从返回 JSON 提取候选域名
  • record_mapping必填白名单字段注册表(后续过滤/评分只能引用这里登记的逻辑字段)
  • record_filter:按记录字段做排除(个性化策略应放这里)
  • domain_filter:按域名字符串做 include/exclude
  • scoring:如何按配置字段排序(支持 weighted_average / lexicographic
  • healthcheck:可选 TLS 检测
  • selection:候选截断数量
  • output:runtime 文件输出路径与文件名
  • v2ray:模板替换输出(可选)
  • notify:后置命令回调(可选)

record_mapping 最小必填示例(domaincreated_at 必须注册):

"record_mapping": {
  "records_path": "data.good[]",
  "field_map": {
    "domain": "ip",
    "created_at": "createdTime",
    "avg_score": "avgScore",
    "yd_score": "ydScore",
    "dx_score": "dxScore",
    "lt_score": "ltScore",
    "avg_latency": "avgLatency",
    "avg_pkg_lost_rate": "avgPkgLostRate",
    "yd_latency": "ydLatency",
    "yd_pkg_lost_rate": "ydPkgLostRate",
    "lt_latency": "ltLatency",
    "lt_pkg_lost_rate": "ltPkgLostRate",
    "dx_latency": "dxLatency",
    "dx_pkg_lost_rate": "dxPkgLostRate",
    "location_country": "locationCountry",
    "location_city": "locationCity"
  },
  "created_time_formats": ["%Y-%m-%d %H:%M:%S"],
  "created_time_timezone": "UTC"
}

record_filter 示例(排除 locationCountry/locationCity 含“泛播”的记录):

"record_filter": {
  "enabled": true,
  "exclude_if_any": [
    { "field": "location_country", "contains": "泛播", "case_sensitive": false },
    { "field": "location_city", "contains": "泛播", "case_sensitive": false }
  ]
}

scoring 示例(avg_score 默认最高权重):

"scoring": {
  "enabled": true,
  "strategy": "weighted_average",
  "weighted_fields": [
    { "field": "avg_score", "weight": 0.5 },
    { "field": "yd_score", "weight": 0.2 },
    { "field": "dx_score", "weight": 0.1 },
    { "field": "lt_score", "weight": 0.2 }
  ],
  "prefer_lower": false,
  "within_hours": 24,
  "tie_breakers": [
    { "field": "created_at", "order": "desc" },
    { "field": "domain", "order": "asc" }
  ]
}

规则支持:

  • contains
  • equals
  • regex

说明:record_filter / scoring 引用未在 record_mapping.field_map 注册的字段时会 fail-fast;服务主流程、日志输出、runtime 文件写入逻辑保持不变。

3.3 语法检查

python3 -m py_compile scripts/domain_updater.py
python3 -m py_compile scripts/update_vmess_links.py

3.4 运行一次

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

3.5 本地查看结果

cat runtime/current_domain.txt
cat runtime/current_domain.json

可选 HTTP 验证:

python3 -m http.server 8080 --directory runtime
curl http://127.0.0.1:8080/current_domain.json

4. Debian 一键部署(完整教程)

4.1 前置条件

  • Debian/Ubuntu
  • 项目已 git clone 到服务器(在仓库目录执行安装)
  • 远程仓库 origin 可用
  • 用于运行服务的用户有仓库读写权限

4.2 推荐方案(不传参数)

如果你采用“每台机器先手动保存 git 凭证”的流程,直接执行:

sudo bash scripts/install_debian.sh

默认行为:

  • 服务用户:当前 sudo 执行前用户(SUDO_USER
  • 定时间隔:1h
  • 自动 push:开启(--git-push 1
  • 认证模式:credential.helper store
  • 推送分支:runtime-state

4.3 Git 凭证(无交互)配置建议

方式 A:手动存凭证(你当前采用的方式)

服务用户下执行一次:

git config --global credential.helper store
git push origin runtime-state:runtime-state

首次输入用户名/密码(或 PAT)后,后续 systemd 可无交互 push。

关键点:保存凭证的用户必须和 service 的 User= 一致。

方式 B:安装脚本带 token(可选)

sudo bash scripts/install_debian.sh \
  --git-http-username <your-user> \
  --git-http-token-file /root/.config/vmess-token \
  --git-use-credential-store 1

4.4 安装后验证

sudo systemctl status vmess-domain-rotator.timer
sudo systemctl status vmess-domain-rotator.service

# 手动触发一次
sudo systemctl start vmess-domain-rotator.service

# 看日志
sudo journalctl -u vmess-domain-rotator.service -n 120 --no-pager

成功时应看到:

  • updater 输出 JSON
  • committed runtime changes on runtime-state ...
  • pushed to origin/runtime-state

5. install_debian.sh 参数说明

sudo bash scripts/install_debian.sh [options]
参数 说明 默认值
--user <name> 指定 service 用户 当前 sudo 用户
--group <name> 指定 service 用户组 当前 sudo 用户主组
--interval <value> 定时周期(如 1h/5min 1h
--git-push <0\|1> 是否自动 push 1
--git-push-remote <name> 远程名 origin
--git-http-username <u> HTTPS 认证用户名 git
--git-http-token <t> HTTPS token(明文参数)
--git-http-token-file <f> 从文件读取 token
--git-use-credential-store <0\|1> 是否使用 credential.helper store 1
--git-credentials-file <f> 指定 credential store 文件路径 空(Git 默认)
--no-install-deps 跳过 apt 安装依赖 关闭
-h, --help 查看帮助 -

说明:

  • --git-push 1 时,push 失败会返回非 0,systemd 任务标记失败(便于监控)。
  • 安装会写入环境文件:/etc/vmess-domain-rotator.env

5.1 systemd unit 生成说明(示例)

install_debian.sh 会按安装参数动态写入 /etc/systemd/system/vmess-domain-rotator.service/etc/systemd/system/vmess-domain-rotator.timer。仓库不再维护 systemd/* 静态模板文件。

service 示例(安装后实际内容会替换成你的参数):

[Unit]
Description=VMess Domain Rotator updater
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
User=<RUN_USER>
Group=<RUN_GROUP>
WorkingDirectory=<APP_DIR>
EnvironmentFile=-/etc/vmess-domain-rotator.env
UMask=0077
ExecStart=/bin/bash <APP_DIR>/scripts/run_update_and_commit.sh <APP_DIR>/config.json

timer 示例(OnUnitActiveSec--interval 决定):

[Unit]
Description=Run VMess Domain Rotator every <INTERVAL>

[Timer]
OnBootSec=2min
OnUnitActiveSec=<INTERVAL>
AccuracySec=30s
Unit=vmess-domain-rotator.service
Persistent=true

[Install]
WantedBy=timers.target

6. 自动提交/推送逻辑说明

scripts/run_update_and_commit.sh 的行为:

  1. 运行 domain_updater.py 更新根目录 runtime/
  2. 读取本次选出的域名,并与 runtime-state 分支上次记录的域名比较
  3. 域名相同则直接跳过 commit/push(会输出 skip 日志)
  4. 域名变化时,将 runtime/ 下四个文件同步到 runtime-state worktree,再 commit
  5. --git-push 1 时要求 push 成功

手动强制提交(忽略“域名相同”与“无变更”跳过逻辑):

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

说明:强制模式会使用 manual: 前缀的提交信息(包含域名和更新时间);若内容无变化,会创建 empty commit 后继续按配置 push。


7. 常用运维命令

7.1 service / timer

sudo systemctl status vmess-domain-rotator.timer
sudo systemctl status vmess-domain-rotator.service
sudo systemctl start vmess-domain-rotator.service
sudo systemctl restart vmess-domain-rotator.timer

7.2 日志

sudo journalctl -u vmess-domain-rotator.service -n 200 --no-pager
sudo journalctl -u vmess-domain-rotator.service -f

7.3 查看 runtime-state 提交

git log runtime-state --oneline -n 20

8. 卸载

sudo bash scripts/uninstall_debian.sh

保留认证/env 文件:

sudo bash scripts/uninstall_debian.sh --keep-auth-files

9. VMess 链接批量替换(可选)

python3 scripts/update_vmess_links.py \
  --input ./nodes.txt \
  --output ./nodes.updated.txt \
  --domain-file ./runtime/current_domain.txt

仅替换匹配名称(ps)的节点:

python3 scripts/update_vmess_links.py \
  --input ./nodes.txt \
  --output ./nodes.updated.txt \
  --domain-file ./runtime/current_domain.txt \
  --name-regex "(argo|cf|vm)"

10. 注意事项

  1. 服务用户与 git 凭证用户必须一致,否则会出现:
    • fatal: could not read Username ... terminal prompts disabled
  2. credential.helper store 为明文存储,建议仅在可控服务器使用。
  3. 不要把 token 提交进仓库。
  4. runtime/state.json 需要持久化,保障 fallback 能用。