diff --git a/solixauto/service.py b/solixauto/service.py index bcde3c7..1ff77d1 100644 --- a/solixauto/service.py +++ b/solixauto/service.py @@ -2,6 +2,7 @@ import os import subprocess import sys from pathlib import Path +from xml.sax.saxutils import escape as xml_escape from . import paths @@ -73,13 +74,20 @@ def environment(): def launchd_plist(profile_name): - label = service_label(profile_name) + label = xml_escape(service_label(profile_name)) + python = xml_escape(preferred_python()) script = script_path() + script_escaped = xml_escape(script) + working_dir = xml_escape(str(Path(script).parent)) + profile_arg = xml_escape(profile_name) log_dir = paths.LOG_DIR env_entries = "" for key, value in environment().items(): - env_entries += f" {key}\n {value}\n" + env_entries += ( + f" {xml_escape(key)}\n" + f" {xml_escape(value)}\n" + ) env_block = "" if env_entries: @@ -90,6 +98,9 @@ def launchd_plist(profile_name): " \n" ) + out_path = xml_escape(str(log_dir / f"{profile_name}.out.log")) + err_path = xml_escape(str(log_dir / f"{profile_name}.err.log")) + return f""" @@ -100,15 +111,15 @@ def launchd_plist(profile_name): ProgramArguments - {preferred_python()} - {script} + {python} + {script_escaped} run - {profile_name} + {profile_arg} --quiet WorkingDirectory - {Path(script).parent} + {working_dir} {env_block} RunAtLoad @@ -120,19 +131,29 @@ def launchd_plist(profile_name): 60 StandardOutPath - {log_dir / f"{profile_name}.out.log"} + {out_path} StandardErrorPath - {log_dir / f"{profile_name}.err.log"} + {err_path} """ +def _systemd_quote(value): + escaped = str(value).replace("\\", "\\\\").replace('"', '\\"') + return f'"{escaped}"' + + def systemd_unit(profile_name): script = script_path() + exec_start = " ".join( + _systemd_quote(token) + for token in (preferred_python(), script, "run", profile_name, "--quiet") + ) env_lines = "".join( - f"Environment={key}={value}\n" for key, value in environment().items() + f"Environment={_systemd_quote(f'{key}={value}')}\n" + for key, value in environment().items() ) return f"""[Unit] @@ -141,7 +162,7 @@ After=network-online.target [Service] Type=simple -ExecStart={preferred_python()} {script} run {profile_name} --quiet +ExecStart={exec_start} WorkingDirectory={Path(script).parent} {env_lines}Restart=always RestartSec=60 @@ -158,7 +179,7 @@ def windows_instructions(profile_name): others. Use Task Scheduler: schtasks /create /tn "{label}" /sc onlogon /rl highest ^ - /tr "\\"{preferred_python()}\\" \\"{script}\\" run {profile_name} --quiet" + /tr "\\"{preferred_python()}\\" \\"{script}\\" run \\"{profile_name}\\" --quiet" To remove it: