#!/usr/bin/env python3 # -*- coding: utf-8 -*- r"""Linux/macOS 服务主体 —— systemd (`Type=simple`) 的前台守护进程 (2026-09-17 用户令 1)。 为什么是"前台常驻"而不是让 systemd 直接跑 `guanlan.py serve`: `guanlan.py serve` 起完 6 个组件就**返回**(组件是 detached 的),systemd 会以为"主进程退出", 于是 `Restart=always` 会不停重启、也管不了组件死活。所以这里做一个**常驻守护**: ExecStart= scripts/service_main.py # 起组件 → 每 15 s 巡检(缺谁补谁)→ 收 SIGTERM 时全停 Type=simple / Restart=always / KillMode=process 用法: python scripts/service_main.py # 前台守护(systemd 用这个) python scripts/service_main.py --once # 只跑一轮巡检就退出(无 root 也能自证) python scripts/service_main.py --selftest # 前置条件自检 注册/卸载走 `scripts/service_ctl.py`(需 root),或用 install.sh --service。 """ from __future__ import annotations import pathlib import signal import sys import threading ROOT = pathlib.Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) sys.path.insert(0, str(ROOT / 'scripts')) import service_worker as SW # noqa: E402 def main() -> int: if '--selftest' in sys.argv: return SW.selftest() stop_evt = threading.Event() def _on_term(signum, frame): SW.log(f'收到信号 {signum} → 停服') stop_evt.set() signal.signal(signal.SIGTERM, _on_term) signal.signal(signal.SIGINT, _on_term) SW.log('服务模式启动(systemd Type=simple)') SW.start() try: SW.supervise(stop_evt, once=('--once' in sys.argv)) finally: if '--once' not in sys.argv: SW.stop() SW.log('服务已退出') return 0 if __name__ == '__main__': sys.exit(main())