71 lines
2.1 KiB
Python
71 lines
2.1 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import argparse
|
||
|
|
import ctypes
|
||
|
|
import locale
|
||
|
|
import os
|
||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
|
||
|
|
def _set_console_title(title: str) -> None:
|
||
|
|
if os.name == "nt":
|
||
|
|
ctypes.windll.kernel32.SetConsoleTitleW(title)
|
||
|
|
|
||
|
|
|
||
|
|
def main() -> int:
|
||
|
|
parser = argparse.ArgumentParser(description="Run a service in a visible console and tee its output to a log file.")
|
||
|
|
parser.add_argument("--title", default="后台服务")
|
||
|
|
parser.add_argument("--log", required=True)
|
||
|
|
parser.add_argument("--pid-file", required=True)
|
||
|
|
parser.add_argument("command", nargs=argparse.REMAINDER)
|
||
|
|
args = parser.parse_args()
|
||
|
|
|
||
|
|
command = list(args.command)
|
||
|
|
if command and command[0] == "--":
|
||
|
|
command.pop(0)
|
||
|
|
if not command:
|
||
|
|
parser.error("missing service command after --")
|
||
|
|
|
||
|
|
_set_console_title(args.title)
|
||
|
|
log_path = Path(args.log)
|
||
|
|
pid_path = Path(args.pid_file)
|
||
|
|
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||
|
|
pid_path.parent.mkdir(parents=True, exist_ok=True)
|
||
|
|
|
||
|
|
encoding = locale.getpreferredencoding(False) or "utf-8"
|
||
|
|
with log_path.open("a", encoding="utf-8") as log_file:
|
||
|
|
process = subprocess.Popen(
|
||
|
|
command,
|
||
|
|
stdin=subprocess.DEVNULL,
|
||
|
|
stdout=subprocess.PIPE,
|
||
|
|
stderr=subprocess.STDOUT,
|
||
|
|
text=True,
|
||
|
|
encoding=encoding,
|
||
|
|
errors="replace",
|
||
|
|
bufsize=1,
|
||
|
|
shell=False,
|
||
|
|
)
|
||
|
|
pid_path.write_text(str(process.pid), encoding="ascii")
|
||
|
|
assert process.stdout is not None
|
||
|
|
try:
|
||
|
|
for line in process.stdout:
|
||
|
|
print(line, end="", flush=True)
|
||
|
|
log_file.write(line)
|
||
|
|
log_file.flush()
|
||
|
|
return process.wait()
|
||
|
|
except KeyboardInterrupt:
|
||
|
|
process.terminate()
|
||
|
|
return process.wait()
|
||
|
|
finally:
|
||
|
|
process.stdout.close()
|
||
|
|
try:
|
||
|
|
pid_path.unlink()
|
||
|
|
except FileNotFoundError:
|
||
|
|
pass
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
raise SystemExit(main())
|