主机:Siche-Ubuntu (192.168.0.64)
服务:AdGuardHome v0.107.77
影响:DNS 解析服务中断
恢复时间:2026-07-09
状态:✅ 已恢复
一、问题摘要
AdGuardHome 服务反复重启失败,systemctl status 显示 Active: activating (auto-restart),进程退出码 1。经排查,根因由三类问题叠加形成:
| # |
类别 |
严重度 |
说明 |
| 1 |
端口占用 |
高 |
libvirt dnsmasq 抢占 UDP 53 端口 |
| 2 |
配置错误 |
高 |
bind_hosts 包含不存在的 IP (192.168.0.24) |
| 3 |
数据损坏 |
中 |
sessions.db 损坏/锁定导致 SQLite 打开超时 |
二、时间线
| 时间点 |
操作 |
| T0 |
用户发现 AdGuardHome 不可用 |
| T1 |
journalctl / systemctl status 确认服务反复重启 |
| T2 |
前台启动捕获错误:listen udp 192.168.0.24:53: bind: cannot assign requested address |
| T3 |
修正确认 192.168.0.24 不存在于任何网卡,仅 192.168.0.64 可用 |
| T4 |
停止 libvirt dnsmasq,释放 192.168.122.1:53 |
| T5 |
修改 bind_hosts → [127.0.0.1, 192.168.0.64, ::1] |
| T6 |
再次启动,新错误:sessions.db: timeout |
| T7 |
排查磁盘 I/O(正常)、文件锁(无持有者)、权限(正常) |
| T8 |
发现 querylog.json 膨胀至 8.9 GB |
| T9 |
备份并删除 sessions.db,清空 querylog.json |
| T10 |
重新启动 → 成功,服务稳定运行 |
三、详细排查
3.1 UDP 53 端口占用
1 2
| netstat -tulpn | grep ':53'
|
根因:libvirt 默认虚拟网络 (virbr0) 自带的 dnsmasq 实例监听了 192.168.122.1:53,与 AdGuardHome 的 DNS 监听需求冲突。
修复:
1 2
| virsh net-destroy default virsh net-autostart default --disable
|
3.2 bind_hosts 无效 IP
配置文件中 bind_hosts 数组包含 192.168.0.24,但该地址未被分配给任何接口:
1 2
| ip addr show | grep 192.168.0.24
|
AdGuardHome 在初始化 DNS 监听器时 bind(2) 调用失败,返回 EADDRNOTAVAIL,直接阻止服务启动。
修复:将 bind_hosts 修正为实际存在的地址:
1 2 3 4
| bind_hosts: - 127.0.0.1 - 192.168.0.64 - "::1"
|
3.3 sessions.db 超时
端口和配置修复后,前台启动仍报错:
1 2
| session_storage: opening db filename=/opt/AdGuardHome/data/sessions.db err=timeout fatal: initializing auth module: creating session storage: timeout
|
排除因素:
- 磁盘 I/O:
iostat 显示 %util < 1%,排除性能瓶颈
- 文件锁:
lsof /opt/AdGuardHome/data/sessions.db 无进程持有
- 权限:
root:root / 600,正常
推测原因:
sessions.db 内部 SQLite 锁未正确释放(如上次进程被 SIGKILL)
querylog.json 高达 8.9 GB,文件系统元数据操作延迟间接影响 db 打开
修复:
1 2 3 4
| systemctl stop AdGuardHome rm -f /opt/AdGuardHome/data/sessions.db > /opt/AdGuardHome/data/querylog.json systemctl start AdGuardHome
|
四、根因分析(5 Why)
- 为什么服务起不来? → DNS 监听器初始化失败 + session 存储初始化失败
- 为什么 DNS 监听失败? → 配置中绑定了不存在的 IP
192.168.0.24
- 为什么 session 也失败? →
sessions.db 损坏/锁定,SQLite 打开超时
- 为什么 db 会损坏? → 服务异常退出时未清理锁,且
querylog.json 过大加剧 I/O 延迟
- 为什么 querylog 这么大? → 查询日志无保留期限制,长期累积
五、修复措施
| 措施 |
操作 |
| 关闭 libvirt dnsmasq |
virsh net-destroy default && virsh net-autostart default --disable |
| 修正 bind_hosts |
移除 192.168.0.24,保留实际 IP |
| 重建 sessions.db |
删除损坏文件,让服务重建 |
| 清空 querylog.json |
释放 8.9 GB 空间 |
六、预防改进
| # |
措施 |
优先级 |
| 1 |
日志轮转:在 AdGuardHome Web UI → 设置 → 查询日志,设置保留期限(建议 7 天) |
P0 |
| 2 |
配置校验:部署前运行 AdGuardHome --check-config 验证 bind_hosts |
P1 |
| 3 |
大文件告警:Prometheus 添加 node_filesystem_file_size_bytes 规则,querylog.json > 1GB 触发告警 |
P1 |
| 4 |
数据库保护:考虑将 sessions.db 移至 tmpfs(内存文件系统),避免磁盘 I/O 依赖 |
P2 |
| 5 |
升级 AdGuardHome:关注 v0.107.77 后续版本是否优化 session 超时机制 |
P2 |
| 6 |
端口规划:libvirt 如恢复使用,需配置 AdGuardHome 不监听 192.168.122.1:53(或给 virbr0 换网段) |
P3 |
七、验证结果
1 2 3 4 5 6 7 8
| systemctl status AdGuardHome | head -3
curl -sI http://192.168.0.64:8008 | head -1
dig @192.168.0.64 baidu.com +short
|
八、附录
8.1 关键路径
| 文件 |
路径 |
| 二进制 |
/opt/AdGuardHome/AdGuardHome |
| 配置 |
/opt/AdGuardHome/AdGuardHome.yaml |
| 数据目录 |
/opt/AdGuardHome/data/ |
| sessions.db |
/opt/AdGuardHome/data/sessions.db |
| querylog.json |
/opt/AdGuardHome/data/querylog.json |
8.2 恢复 libvirt(如需)
1 2 3
| virsh net-start default virsh net-autostart default
|
8.3 重置管理员密码