#!/usr/bin/env python3 from __future__ import annotations import argparse import os from pathlib import Path import plistlib import subprocess PROJECT_DIR = Path(__file__).resolve().parents[1] LABEL = "com.xsk.records.sync" PLIST_PATH = Path.home() / "Library" / "LaunchAgents" / f"{LABEL}.plist" LOG_DIR = Path.home() / "Library" / "Logs" / "xsk-records-web" def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="安装新时空课程记录同步 LaunchAgent") parser.add_argument("--use-sshpass", action="store_true", default=os.getenv("XSK_USE_SSHPASS", "") == "1") parser.add_argument("--ssh-password", default=os.getenv("XSK_SSH_PASSWORD")) return parser.parse_args() def main() -> int: args = parse_args() LOG_DIR.mkdir(parents=True, exist_ok=True) PLIST_PATH.parent.mkdir(parents=True, exist_ok=True) program_arguments = [ "/usr/bin/python3", str(PROJECT_DIR / "scripts" / "sync_to_vps.py"), ] if args.use_sshpass: program_arguments.append("--use-sshpass") environment = { "PATH": "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin", } if args.use_sshpass and args.ssh_password: environment["XSK_SSH_PASSWORD"] = args.ssh_password plist = { "Label": LABEL, "ProgramArguments": program_arguments, "RunAtLoad": True, "KeepAlive": True, "StandardOutPath": str(LOG_DIR / "sync.log"), "StandardErrorPath": str(LOG_DIR / "sync.err.log"), "EnvironmentVariables": environment, } with PLIST_PATH.open("wb") as handle: plistlib.dump(plist, handle) subprocess.run(["launchctl", "unload", str(PLIST_PATH)], check=False, capture_output=True) subprocess.run(["launchctl", "load", str(PLIST_PATH)], check=True) print(f"已安装并启动 LaunchAgent: {PLIST_PATH}") return 0 if __name__ == "__main__": raise SystemExit(main())