AdGuardHome API 实战:4 个运维场景 + 1 套 Python 自动化脚本模板
AdGuardHome API 实战4 个运维场景 1 套 Python 自动化脚本模板【免费下载链接】AdGuardHomeNetwork-wide ads trackers blocking DNS server项目地址: https://gitcode.com/gh_mirrors/ad/AdGuardHome每天进 Web 界面手点一次“刷新规则”故障排查时翻不到想要的查询记录拦截率到底多少心里没底——这些重复劳动适合交给脚本。AdGuardHome API 走的是 HTTP 协议、Basic Auth 认证用 Python 写自动化脚本巡检、取证、监控几行代码就能固化下来。从架构图能看出关键点Web 界面本身只是这套 REST API 的客户端之一Query log、Stats、Filters 等模块全部挂在同一个 API 层上。也就是说你的脚本和界面走的是完全相同的通道界面上能做的API 都能做。 先用一个 Session 打通 GET /control/status依赖只有一个。认证信息在整个脚本里只写一次挂到requests.Session上后续所有请求自动携带不再重复传。# 依赖安装pip install requests import requests # 主机与认证只写一次后面所有小节复用这个 session AGH_URL http://192.168.0.200:80 session requests.Session() session.auth (admin, admin) # 换成你的管理员账号 session.headers.update({Content-Type: application/json}) # 首次调用拿服务器状态 status session.get(f{AGH_URL}/control/status, timeout10).json() print(status[protection_enabled], status[running], status[version])GET /control/status返回protection_enabled保护是否开启、running、dns_addresses、dns_port、version等字段是任何巡检逻辑的第一站。如果这一行跑通了剩下的场景只是换路径和参数。过滤规则自动开关与刷新目的规则源更新后不用再进界面点刷新过滤开关也能被脚本控制。POST /control/filtering/config负责启停interval是自动刷新间隔单位小时POST /control/filtering/add_url追加规则源POST /control/filtering/refresh立即重新下载合并全部规则。# 开启 DNS 过滤并设定 24 小时的自动刷新间隔 session.post(f{AGH_URL}/control/filtering/config, json{enabled: True, interval: 24}) # 追加规则源url 换成你自己的指向本地镜像更稳 session.post(f{AGH_URL}/control/filtering/add_url, json{url: http://192.168.0.255/lists/ads.txt, name: local-ads, whitelist: False}) # 立即重新下载并合并全部规则 session.post(f{AGH_URL}/control/filtering/refresh)这些规则源维护的就是上图里 Rewrite、Lists 环节的数据请求在到达上游 DNS 之前就会被拦下。坑在refresh它是同步调用规则列表多时耗时远超 10 秒要单独放宽超时add_url传重复的url会被拒绝追加前先查现有列表。查询日志拉取与清空目的排查“某域名为什么没解析出来”时秒级把证据捞出来而不是在界面里翻页。GET /control/querylog支持limit控制条数、search按域名或客户端 IP 过滤。# 取最近 50 条并按域名过滤 log session.get(f{AGH_URL}/control/querylog, params{limit: 50, search: ads.example.com}).json() for item in log[data]: print(item[time], item[client], item[name], item[status], item[reason])返回体是{oldest, data}data每条含name域名、client来源 IP、upstream、status、reason、cached等字段status能区分是规则拦截、安全浏览替换还是搜索改写。清空只有一个接口且不可恢复session.post(f{AGH_URL}/control/querylog_clear) # 建议先落盘备份再执行查询量与拦截量周期监控目的让拦截量从“看不见”变成周期采样的数字。GET /control/stats一次拿到全部计数。stats session.get(f{AGH_URL}/control/stats).json() total stats[num_dns_queries] blocked stats[num_blocked_filtering] print(f查询 {total}拦截 {blocked}拦截率 {blocked / max(total, 1):.1%})返回里还有num_replaced_safebrowsing、num_replaced_safesearch、num_replaced_rewrites等分项。监控别写死循环常驻进程让定时任务每 5 分钟采样一次、把结果追加到文件需要归零统计窗口时再调POST /control/stats_reset。上游 DNS 配置查询与健康测试目的上游挂了时先确认是谁的锅。GET /control/dns_info读出当前配置POST /control/test_upstream_dns实测可达性。dns session.get(f{AGH_URL}/control/dns_info).json() # 测试一组上游是否可用bootstrap_dns 负责解析上游域名 result session.post(f{AGH_URL}/control/test_upstream_dns, json{bootstrap_dns: [1.1.1.1], upstream_dns: dns[upstream_dns]}).json() bad {k: v for k, v in result.items() if v ! OK} print(异常上游, bad or 无)返回体里每个上游对应一个状态OK表示可达其余是具体错误文本比如i/o timeout。写入侧同理POST /control/dns_config提交改后的配置模式与上面的读-测-写一致不再重复。 把脚本做稳重试、超时与状态码集中封装前面为了省事没写异常处理。上生产前把重试、超时、401/404/5xx 集中封装进一个工具函数调用处保持干净而不是散落满屏 try/exceptimport time def call(session, method, path, retries3, **kwargs): 统一出口超时、重试、状态码判断都在这里 kwargs.setdefault(timeout, 15) for attempt in range(retries): try: resp session.request(method, f{AGH_URL}{path}, **kwargs) except requests.exceptions.RequestException as e: # 连接失败/超时退避重试最后一次直接抛出 if attempt retries - 1: time.sleep(2 * (attempt 1)) continue raise e if resp.status_code 401: # 凭证失效重试无意义 raise PermissionError(认证失败检查 Basic Auth 账号密码) if resp.status_code 404: # 路径拼错或 API 版本不匹配 raise ValueError(f接口不存在{path}) if resp.status_code 500 and attempt retries - 1: time.sleep(2 * (attempt 1)) # 5xx退避重试 continue resp.raise_for_status() return resp.json()调用处只剩一行call(session, GET, /control/status)。401 和 404 必须区分对待前者是凭证问题后者多半是路径或版本不对都别盲目重试。接口全集以官方定义 openapi/openapi.yaml 为准想扩展别的操作直接查它。调度交给 cronWindows 用任务计划程序脚本本身保持幂等、无状态*/5 * * * * /usr/bin/python3 /opt/scripts/agh_monitor.py /var/log/agh_monitor.log 21完整脚本复制即可运行把上面所有场景合成单main的可运行版本凭证走环境变量不落代码库#!/usr/bin/env python3 AdGuardHome 日常运维状态巡检、规则刷新、日志取证、统计采样 import json import os import time import requests AGH_URL os.environ.get(AGH_URL, http://192.168.0.200:80) AUTH (os.environ.get(AGH_USER, admin), os.environ.get(AGH_PASS, )) def build_session(): 认证只在这里出现一次 s requests.Session() s.auth AUTH s.headers.update({Content-Type: application/json}) return s def call(session, method, path, retries3, **kwargs): 统一出口超时、重试、状态码判断 kwargs.setdefault(timeout, 15) for attempt in range(retries): try: resp session.request(method, f{AGH_URL}{path}, **kwargs) except requests.exceptions.RequestException as e: if attempt retries - 1: time.sleep(2 * (attempt 1)) continue raise e if resp.status_code 401: raise PermissionError(认证失败检查 Basic Auth 凭证) if resp.status_code 404: raise ValueError(f接口不存在{path}) if resp.status_code 500 and attempt retries - 1: time.sleep(2 * (attempt 1)) continue resp.raise_for_status() return resp.json() def main(): session build_session() # 1) 状态巡检 print(json.dumps(call(session, GET, /control/status), ensure_asciiFalse)) # 2) 过滤规则确保开启 触发刷新规则多时放宽超时 call(session, POST, /control/filtering/config, json{enabled: True, interval: 24}) call(session, POST, /control/filtering/refresh, timeout120) # 3) 日志取证最近 200 条落盘不直接清空 log call(session, GET, /control/querylog, params{limit: 200}) with open(/tmp/agh_querylog.json, w, encodingutf-8) as f: json.dump(log[data], f, ensure_asciiFalse, indent2) # 4) 统计采样 print(json.dumps(call(session, GET, /control/stats), ensure_asciiFalse)) if __name__ __main__: main()✅ 上线前自查清单凭证经环境变量或配置下发没有硬编码在脚本和仓库里AGH_URL从脚本所在主机可达管理端口常只绑定内网querylog_clear、stats_reset不可逆执行前已有落盘备份cron 行带日志重定向脚本幂等、可重复执行refresh的超时按实际规则源数量调整120 秒起步两个延伸方向把第 4 步的统计输出接给 Prometheus 或 Grafana拦截率就有历史曲线了照着 openapi/openapi.yaml 把 DNS 重写、客户端管理等接口纳入同一个call()脚本骨架不用动。【免费下载链接】AdGuardHomeNetwork-wide ads trackers blocking DNS server项目地址: https://gitcode.com/gh_mirrors/ad/AdGuardHome创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考