Background services without systemd (runit, OpenRC, ...)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
sarahandClaude Opus 5.5 committed 2026-10-13 17:51:30 +02:00
1 parent e7e233951f
commit f63e708572
8 files changed
+325 -110

No files matched your search

+2 -55
View File
@@ -3,7 +3,7 @@
Linux Windows
.desktop entry Start Menu shortcut (.lnk)
systemd --user service shortcut in the Startup folder, started and stopped
through Programs/ServiceRun.py (which records its PID)
through Programs/ServiceRun.py (Services.py)
system python3 the py launcher / python.exe, else winget installs it
fc-list the Fonts registry key
@@ -17,13 +17,12 @@ import subprocess
from pathlib import Path
from typing import Callable, Optional
from Core import DataHome, ServicesDir
from Core import DataHome
LogFn = Callable[[str], None]
# Child processes of a windowed program would each flash a console window.
NoWindow = getattr(subprocess, "CREATE_NO_WINDOW", 0)
_Detached = getattr(subprocess, "DETACHED_PROCESS", 0) | getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)
PythonVersion = "3.14" # what winget installs when there's no Python yet
_WingetId = f"Python.Python.{PythonVersion}"
@@ -115,58 +114,6 @@ def InstallPython(Log: LogFn) -> Optional[str]:
return FindPython()
# --- Background services (SaraSortd) ---------------------------------------------------
def _PidFile(Name: str) -> Path:
return ServicesDir / f"{Name}.pid"
def ServicePid(Name: str) -> Optional[int]:
"""The PID ServiceRun.py recorded, if that process is still alive."""
try:
Pid = int(_PidFile(Name).read_text().strip())
except (OSError, ValueError):
return None
try:
Output = subprocess.run(
["tasklist", "/FI", f"PID eq {Pid}", "/NH", "/FO", "CSV"],
capture_output=True, text=True, timeout=15, creationflags=NoWindow,
).stdout
except (OSError, subprocess.SubprocessError):
return None
return Pid if re.search(rf'"{Pid}"', Output) else None
def StartService(Name: str, PythonW: Path, Runner: Path, Script: Path, WorkingDir: Path, Log: LogFn) -> None:
"""Start a background service now (it's also started at every login by
its Startup shortcut, which runs the same command)."""
if ServicePid(Name) is not None:
Log(f"{Name} is already running")
return
WorkingDir.mkdir(parents=True, exist_ok=True)
subprocess.Popen(
[str(PythonW), str(Runner), Name, str(Script)], cwd=str(WorkingDir),
creationflags=_Detached | NoWindow, close_fds=True,
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
)
Log(f"Started {Name}")
def StopService(Name: str, Log: LogFn) -> None:
Pid = ServicePid(Name)
if Pid is not None:
subprocess.run(["taskkill", "/PID", str(Pid), "/T", "/F"], capture_output=True, creationflags=NoWindow)
Log(f"Stopped {Name}")
_PidFile(Name).unlink(missing_ok=True)
def RestartService(Name: str, PythonW: Path, Runner: Path, Script: Path, WorkingDir: Path, Log: LogFn) -> None:
if ServicePid(Name) is not None:
StopService(Name, Log)
StartService(Name, PythonW, Runner, Script, WorkingDir, Log)
# --- Fonts -----------------------------------------------------------------------------------