#!/usr/bin/env python3 """从 /opt/live/config(或 LIVE_CONFIG_ROOT)JSON 配置生成 system-stack.env,供现有 service_ctl / install 脚本读取。""" from __future__ import annotations import json import os import sys from pathlib import Path def config_root() -> Path: env = os.environ.get("LIVE_CONFIG_ROOT", "").strip() if env: return Path(env) if Path("/opt/live/config/system.json").is_file(): return Path("/opt/live/config") here = Path(__file__).resolve() return here.parent.parent / "config" / "defaults" def load_json(path: Path) -> dict: if not path.is_file(): return {} return json.loads(path.read_text(encoding="utf-8")) def collect_env(root: Path) -> dict[str, str]: lines: dict[str, str] = {} sys_j = load_json(root / "system.json") web = sys_j.get("web_console") or {} ident = sys_j.get("identity") or {} if ident.get("hostname_alias"): lines["HOSTNAME_ALIAS"] = str(ident["hostname_alias"]) if web.get("api_port") is not None: lines["PORT"] = str(web["api_port"]) net = load_json(root / "network.json") wifi = net.get("wifi") or {} if wifi.get("connection_name"): lines["WIFI_CONNECTION_NAME"] = str(wifi["connection_name"]) if wifi.get("ssid"): lines["WIFI_SSID"] = str(wifi["ssid"]) if wifi.get("psk"): lines["WIFI_PSK"] = str(wifi["psk"]) if net.get("ipv6", {}).get("disable"): lines["DISABLE_IPV6"] = "1" svc_dir = root / "services" if svc_dir.is_dir(): for f in sorted(svc_dir.glob("*.json")): data = load_json(f) env = data.get("env") or {} if not isinstance(env, dict): continue for k, v in env.items(): if v is not None and str(v) != "": lines[str(k)] = str(v) ports = {} if svc_dir.is_dir(): for f in sorted(svc_dir.glob("*.json")): data = load_json(f) pid = data.get("id") or f.stem pr = data.get("ports") or {} if isinstance(pr, dict) and "http" in pr: ports[pid] = pr["http"] # 固定映射:homepage 使用 HOMEPAGE_PORT if "homepage" in ports: lines.setdefault("HOMEPAGE_PORT", str(ports["homepage"])) lines.setdefault("ENABLE_MDNS", "1") lines.setdefault("ENABLE_WIFI_PROFILE", "1") lines.setdefault("ENABLE_BROWSER", "1") lines.setdefault("ENABLE_COCKPIT", "1") return lines def main() -> int: root = config_root() out = Path(os.environ.get("LIVE_ENV_OUT", "/opt/live/generated/system-stack.env")) if len(sys.argv) > 1: out = Path(sys.argv[1]) lines = collect_env(root) out.parent.mkdir(parents=True, exist_ok=True) body = "\n".join(f"{k}={v}" for k, v in sorted(lines.items())) + "\n" out.write_text( "# Generated by live-platform/tools/render_stack_env.py — do not hand-edit\n" + body, encoding="utf-8", ) # 开发树:可选同步到仓库 config(由 install 脚本 ln -sf) print(str(out)) return 0 if __name__ == "__main__": raise SystemExit(main())