fix: ensure zone directory exists before writing; cross-distro chown fallback

新装机器上添加域名报 500:FileNotFoundError '/etc/bind/zones/db.<x>.com'。
根因是创建 zone 时直接 open() 写文件,没先 makedirs,目录不存在
就直接抛 FileNotFoundError。

修法:
1. 写 zone 文件前 os.makedirs(BIND_ZONES_DIR, exist_ok=True),
   PermissionError 时返回用户友好提示而不是 500。
2. 把所有 chown bind:bind 改成 'chown bind:bind 2>/dev/null ||
   chown named:named 2>/dev/null',覆盖 RHEL/CentOS 上 bind 用户
   不存在的场景,避免 chown 报错污染日志。

影响范围:zone_create(创建)、record_edit/delete(修改/删除记录)、
zone_raw_edit(原始文件编辑)四处写文件路径。
This commit is contained in:
Hermes
2026-07-24 17:44:38 +08:00
parent f10ac5591e
commit 903fe1704a
+14 -7
View File
@@ -471,8 +471,8 @@ def append_record_to_file(filepath, name, ttl, rtype, data):
with open(filepath, 'w') as f: with open(filepath, 'w') as f:
f.write(content) f.write(content)
run_cmd(f"chown bind:bind {filepath}") run_cmd(f"chown bind:bind {filepath} 2>/dev/null || chown named:named {filepath} 2>/dev/null")
run_cmd(f"chmod 644 {filepath}")
return True, "OK" return True, "OK"
@@ -541,8 +541,8 @@ def delete_record_from_file(filepath, zone_name, idx):
with open(filepath, 'w') as f: with open(filepath, 'w') as f:
f.write(content) f.write(content)
run_cmd(f"chown bind:bind {filepath}") run_cmd(f"chown bind:bind {filepath} 2>/dev/null || chown named:named {filepath} 2>/dev/null")
run_cmd(f"chmod 644 {filepath}")
return True, f'{deleted["name"]} {deleted["type"]} {deleted["data"]}', "OK" return True, f'{deleted["name"]} {deleted["type"]} {deleted["data"]}', "OK"
@@ -774,9 +774,16 @@ def zone_create():
""" """
# Write zone file # Write zone file
try:
os.makedirs(BIND_ZONES_DIR, exist_ok=True)
except PermissionError as e:
flash(f"无法创建 zone 目录 {BIND_ZONES_DIR}(权限不足):{e}", "error")
return render_template("zone_form.html")
with open(zone_file, 'w') as f: with open(zone_file, 'w') as f:
f.write(zone_content) f.write(zone_content)
run_cmd(f"chown bind:bind {zone_file}") # BIND runs as user 'bind' (Debian/Ubuntu) or 'named' (RHEL/CentOS).
# Try Debian first; fall back to RHEL.
run_cmd(f"chown bind:bind {zone_file} 2>/dev/null || chown named:named {zone_file} 2>/dev/null")
run_cmd(f"chmod 644 {zone_file}") run_cmd(f"chmod 644 {zone_file}")
# Validate zone # Validate zone
@@ -877,8 +884,8 @@ def zone_raw(zone_name):
# Write # Write
with open(zone["file"], 'w') as f: with open(zone["file"], 'w') as f:
f.write(content) f.write(content)
run_cmd(f"chown bind:bind {zone['file']}") run_cmd(f"chown bind:bind {zone['file']} 2>/dev/null || chown named:named {zone['file']} 2>/dev/null")
run_cmd(f"rm -f /tmp/zone_check.tmp") run_cmd(f"chmod 644 {zone['file']}")
bind_reload() bind_reload()