85 lines
2.3 KiB
Python
Executable File
85 lines
2.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import argparse
|
|
import logging
|
|
import plistlib
|
|
import sys
|
|
import typing
|
|
from pathlib import Path
|
|
|
|
|
|
def parse_args(argv: list[str]) -> typing.Tuple[argparse.Namespace, list[str]]:
|
|
def parse_env(env: str) -> typing.Tuple[str, str]:
|
|
return env.split("=", maxsplit=1)
|
|
|
|
def parse_path(path: str) -> Path:
|
|
return Path(path).expanduser().resolve()
|
|
|
|
arger = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
arger.add_argument(
|
|
"-e", "--env", dest="env", metavar="ENVVAR", type=parse_env, nargs="+", help="Environment variables as K=V list"
|
|
)
|
|
arger.add_argument("-w", "--cwd", dest="cwd", default=Path.cwd(), type=parse_path, help="Working directory")
|
|
arger.add_argument("-l", "--label", required=True, help="Label")
|
|
arger.add_argument(
|
|
"--install",
|
|
action="store_true",
|
|
help="Install the plist to ~/Library/LaunchAgents/",
|
|
)
|
|
|
|
if not argv:
|
|
arger.print_help()
|
|
sys.exit(1)
|
|
|
|
args, unknown = arger.parse_known_args()
|
|
if unknown and unknown[0] == "--":
|
|
unknown = unknown[1:]
|
|
|
|
if not unknown:
|
|
arger.print_help()
|
|
sys.exit(1)
|
|
|
|
return args, unknown
|
|
|
|
|
|
def generate_plist(label: str, args: list[str], env: dict, cwd: Path) -> str:
|
|
doc = {
|
|
"Label": label,
|
|
"ProgramArguments": args,
|
|
"EnvironmentVariables": env,
|
|
"WorkingDirectory": str(cwd),
|
|
"RunAtLoad": True,
|
|
"StandardOutPath": str(cwd / f"{label}.stdout.log"),
|
|
"StandardErrorPath": str(cwd / f"{label}.stderr.log"),
|
|
}
|
|
return plistlib.dumps(
|
|
doc,
|
|
fmt=plistlib.FMT_XML,
|
|
sort_keys=True,
|
|
).decode()
|
|
|
|
|
|
def main():
|
|
args, unknown = parse_args(sys.argv[1:])
|
|
print(args, unknown)
|
|
plist_doc = generate_plist(
|
|
label=args.label,
|
|
args=unknown,
|
|
env=dict(args.env),
|
|
cwd=args.cwd,
|
|
)
|
|
print(plist_doc)
|
|
|
|
if args.install:
|
|
install_dir: Path = Path("~/Library/LaunchAgents/").expanduser()
|
|
logging.info(f"Installing plist to {install_dir}")
|
|
|
|
install_path = install_dir / f"{args.label}.plist"
|
|
install_path.write_text(plist_doc)
|
|
|
|
logging.info(f'Run "launchctl load -w {install_path}" to start the service')
|
|
|
|
|
|
if __name__ == "__main__":
|
|
logging.basicConfig(level=logging.INFO)
|
|
main()
|