feat: initial commit
This commit is contained in:
Executable
+80
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Uruchamia komendę w tle, odczepioną od bieżącej sesji terminala.
|
||||
|
||||
Powód istnienia: `nohup ... &` wewnątrz zadania go-task nie wystarcza - interpreter
|
||||
zadania kończy się razem z krokiem i zabija potomka. `start_new_session=True` robi
|
||||
to, co `setsid` na Linuksie, a działa też na macOS, gdzie `setsid` nie istnieje.
|
||||
|
||||
Użycie:
|
||||
daemonize.py --pidfile .runs/llm/mock.pid --log .runs/llm/mock.log -- python3 llm/mock_server.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def already_running(pidfile: Path) -> int | None:
|
||||
if not pidfile.exists():
|
||||
return None
|
||||
try:
|
||||
pid = int(pidfile.read_text().strip())
|
||||
os.kill(pid, 0)
|
||||
except (ValueError, ProcessLookupError, PermissionError, OSError):
|
||||
return None
|
||||
return pid
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument("--pidfile", required=True)
|
||||
parser.add_argument("--log", required=True)
|
||||
parser.add_argument("--stop", action="store_true", help="zatrzymaj proces z pidfile zamiast startować")
|
||||
parser.add_argument("command", nargs=argparse.REMAINDER)
|
||||
args = parser.parse_args()
|
||||
|
||||
pidfile = Path(args.pidfile)
|
||||
pidfile.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if args.stop:
|
||||
pid = already_running(pidfile)
|
||||
if pid is None:
|
||||
print(f"nic nie działa pod {pidfile}")
|
||||
pidfile.unlink(missing_ok=True)
|
||||
return 0
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
pidfile.unlink(missing_ok=True)
|
||||
print(f"zatrzymano pid {pid}")
|
||||
return 0
|
||||
|
||||
command = [arg for arg in args.command if arg != "--"]
|
||||
if not command:
|
||||
parser.error("podaj komendę do uruchomienia po --")
|
||||
|
||||
running = already_running(pidfile)
|
||||
if running is not None:
|
||||
print(f"już działa (pid {running})")
|
||||
return 0
|
||||
|
||||
log = Path(args.log)
|
||||
log.parent.mkdir(parents=True, exist_ok=True)
|
||||
with log.open("ab") as handle:
|
||||
process = subprocess.Popen(
|
||||
command,
|
||||
stdout=handle,
|
||||
stderr=subprocess.STDOUT,
|
||||
stdin=subprocess.DEVNULL,
|
||||
start_new_session=True, # odpowiednik setsid, przenośny między Linuksem a macOS
|
||||
)
|
||||
pidfile.write_text(str(process.pid))
|
||||
print(f"uruchomiono pid {process.pid} (log: {log})")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user