feat: auto-detect BIND paths via os.path.exists fallback chain

环境变量 > 自动探测 > 内置默认值。自动探测按发行版常见路径顺序
回退(Debian/Ubuntu / RHEL/CentOS/Rocky / AlmaLinux / FreeBSD),
大多数情况下无需任何配置。

新增探测函数 _detect_bind_path() 与候选路径字典 _BIND_PATH_CANDIDATES,
覆盖以下发行版默认布局:

  BIND_CONF_DIR:     /etc/bind -> /etc -> /etc/named
  BIND_ZONES_DIR:    /etc/bind/zones -> /var/named -> /var/named/data
  BIND_CONF_LOCAL:   /etc/bind/named.conf.local -> /etc/named.conf.local
  BIND_CONF_OPTIONS: /etc/bind/named.conf.options -> /etc/named.conf
  BIND_RNDC_KEY:     /etc/bind/rndc.key -> /etc/rndc.key -> /var/named/key

环境变量仍然作为最高优先级入口,用于非标准路径或多实例场景。

README 第 5 节改名为'路径优先级',列出三层优先级与探测顺序。
This commit is contained in:
Hermes
2026-07-22 17:31:52 +08:00
parent 1b15592f4d
commit 3d417421ff
2 changed files with 50 additions and 26 deletions
+26 -17
View File
@@ -77,7 +77,7 @@ dns-service/
| `named.conf.local` | Zone 声明(由 Web UI 自动管理) | `/etc/bind/named.conf.local` |
| zone files | DNS 记录文件 | `/etc/bind/zones/db.*` |
> **路径可通过环境变量覆盖**(见下方"路径配置"章节)。RHEL/CentOS/Rocky 默认 BIND 路径为 `/var/named`、`/etc/named.conf`,需要在环境变量里重新指
> **路径自动探测**:服务启动时按常见路径顺序探测实际存在的目录/文件,覆盖 Debian/Ubuntu、RHEL/CentOS/Rocky、AlmaLinux、FreeBSD 等发行版默认布局。如需强制指定,可用环境变量覆盖(见"路径优先级")
## 安装部署
@@ -198,20 +198,33 @@ systemctl enable dns-web
systemctl start dns-web
```
### 5. 路径配置(环境变量)
### 5. 路径优先级
BIND 在不同发行版的默认路径不同,下面这些环境变量可以覆盖默认值(不设置则使用 Debian/Ubuntu 默认)
服务启动时按下面的顺序确定每个 BIND 路径
| 变量 | Debian/Ubuntu 默认 | RHEL/CentOS 推荐值 |
|------|--------------------|--------------------|
| `BIND_CONF_DIR` | `/etc/bind` | `/etc` |
| `BIND_ZONES_DIR` | `/etc/bind/zones` | `/var/named` |
| `BIND_CONF_LOCAL` | `/etc/bind/named.conf.local` | `/etc/named.conf.local` |
| `BIND_CONF_OPTIONS` | `/etc/bind/named.conf.options` | `/etc/named.conf` |
| `BIND_RNDC_KEY` | `/etc/bind/rndc.key` | `/etc/rndc.key` |
| `BIND_SERVICE` | `named` | `named` |
1. **环境变量**(最高优先级,用于强制指定非默认路径)
2. **自动探测**(按常见路径顺序,找到第一个存在的目录/文件)
3. **内置默认值**(都没探测到时使用,主要为 Debian/Ubuntu
在 systemd 服务里加 `Environment=`
自动探测覆盖以下发行版默认布局
| 变量 | 探测顺序 |
|------|----------|
| `BIND_CONF_DIR` | `/etc/bind``/etc``/etc/named` |
| `BIND_ZONES_DIR` | `/etc/bind/zones``/var/named``/var/named/data` |
| `BIND_CONF_LOCAL` | `/etc/bind/named.conf.local``/etc/named.conf.local` |
| `BIND_CONF_OPTIONS` | `/etc/bind/named.conf.options``/etc/named.conf` |
| `BIND_RNDC_KEY` | `/etc/bind/rndc.key``/etc/rndc.key``/var/named/key` |
| `BIND_SERVICE` | 固定 `named` |
大多数情况下**无需任何配置**——Debian 上自然走 `/etc/bind/*`CentOS/RHEL 上自然走 `/var/named` + `/etc/named.conf*`
只有以下两种场景需要用环境变量强制覆盖:
- BIND 装在非标准路径(比如容器里 mount 到 `/opt/bind`
- 同机多实例 / 测试场景,需要指向特定路径
覆盖示例(systemd):
```bash
cat > /etc/systemd/system/dns-web.service << 'EOF'
@@ -223,11 +236,7 @@ After=network.target named.service
Type=notify
User=root
WorkingDirectory=/root/dns-service
Environment=BIND_CONF_DIR=/etc
Environment=BIND_ZONES_DIR=/var/named
Environment=BIND_CONF_LOCAL=/etc/named.conf.local
Environment=BIND_CONF_OPTIONS=/etc/named.conf
Environment=BIND_RNDC_KEY=/etc/rndc.key
Environment=BIND_ZONES_DIR=/opt/bind/zones
ExecStart=/usr/local/bin/gunicorn --workers 2 --bind 0.0.0.0:5300 wsgi:app
Restart=always
RestartSec=5
+24 -9
View File
@@ -27,15 +27,30 @@ app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
# ─── BIND paths ───
# Defaults are Debian/Ubuntu (bind9). Override via env on RHEL/CentOS/Rocky:
# BIND_CONF_DIR=/etc BIND_CONF_LOCAL=/etc/named.conf
# BIND_ZONES_DIR=/var/named BIND_CONF_OPTIONS=/etc/named.conf.options
# BIND_RNDC_KEY=/etc/rndc.key
BIND_CONF_DIR = os.environ.get("BIND_CONF_DIR", "/etc/bind")
BIND_ZONES_DIR = os.environ.get("BIND_ZONES_DIR", "/etc/bind/zones")
BIND_CONF_LOCAL = os.environ.get("BIND_CONF_LOCAL", "/etc/bind/named.conf.local")
BIND_CONF_OPTIONS = os.environ.get("BIND_CONF_OPTIONS", "/etc/bind/named.conf.options")
BIND_RNDC_KEY = os.environ.get("BIND_RNDC_KEY", "/etc/bind/rndc.key")
# 优先级:环境变量 > 自动探测 > 内置默认值。
# 自动探测按"哪个目录/文件存在就用谁"在常见路径里回退,覆盖 Debian/Ubuntu、
# RHEL/CentOS/Rocky、AlmaLinux、FreeBSD 等发行版默认布局;如有特殊安装路径,
# 可用环境变量强制指定。
_BIND_PATH_CANDIDATES = {
"BIND_CONF_DIR": ["/etc/bind", "/etc", "/etc/named"],
"BIND_ZONES_DIR": ["/etc/bind/zones", "/var/named", "/var/named/data"],
"BIND_CONF_LOCAL": ["/etc/bind/named.conf.local", "/etc/named.conf.local"],
"BIND_CONF_OPTIONS": ["/etc/bind/named.conf.options", "/etc/named.conf"],
"BIND_RNDC_KEY": ["/etc/bind/rndc.key", "/etc/rndc.key", "/var/named/key"],
}
def _detect_bind_path(candidates):
"""Return first existing path in candidates; fall back to first (built-in default)."""
for p in candidates:
if os.path.exists(p):
return p
return candidates[0]
BIND_CONF_DIR = os.environ.get("BIND_CONF_DIR", _detect_bind_path(_BIND_PATH_CANDIDATES["BIND_CONF_DIR"]))
BIND_ZONES_DIR = os.environ.get("BIND_ZONES_DIR", _detect_bind_path(_BIND_PATH_CANDIDATES["BIND_ZONES_DIR"]))
BIND_CONF_LOCAL = os.environ.get("BIND_CONF_LOCAL", _detect_bind_path(_BIND_PATH_CANDIDATES["BIND_CONF_LOCAL"]))
BIND_CONF_OPTIONS = os.environ.get("BIND_CONF_OPTIONS", _detect_bind_path(_BIND_PATH_CANDIDATES["BIND_CONF_OPTIONS"]))
BIND_RNDC_KEY = os.environ.get("BIND_RNDC_KEY", _detect_bind_path(_BIND_PATH_CANDIDATES["BIND_RNDC_KEY"]))
BIND_SERVICE = os.environ.get("BIND_SERVICE", "named")
# ─── Record types ───