-
-
Save redraw/4f2d5bd7d98bc23e3ccf5d8542e187ca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env -S uv run -s | |
# /// script | |
# requires-python = ">=3.11" | |
# dependencies = [] | |
# /// | |
import argparse | |
import os | |
import subprocess | |
import shutil | |
SERVICE_TEMPLATE = """[Unit] | |
Description={description} | |
After=network.target | |
[Service] | |
ExecStart={exec_start} | |
Restart=on-failure | |
WorkingDirectory={working_directory} | |
[Install] | |
WantedBy=default.target | |
""" | |
def edit_file(path): | |
editor = os.getenv("EDITOR", "nano") | |
subprocess.run([editor, path]) | |
def create_service(args, service_path, systemd_user_dir): | |
exec_path = shutil.which(args.command[0]) | |
if not exec_path: | |
print(f"Error: Command '{args.command[0]}' not found.") | |
exit(1) | |
full_command = " ".join([exec_path] + args.command[1:]) | |
if not args.desc: | |
args.desc = f'"{args.name}" service unit.' | |
os.makedirs(systemd_user_dir, exist_ok=True) | |
service_content = SERVICE_TEMPLATE.format( | |
description=args.desc, | |
exec_start=full_command, | |
working_directory=args.workdir | |
) | |
try: | |
with open(service_path, "w") as service_file: | |
service_file.write(service_content) | |
except Exception as e: | |
print(f"Error creating service file: {e}") | |
if args.edit: | |
edit_file(service_path) | |
subprocess.run(["systemctl", "--user", "daemon-reload"], check=True) | |
subprocess.run(["systemctl", "--user", "enable", args.name], check=True) | |
subprocess.run(["systemctl", "--user", "start", args.name], check=True) | |
print("User service created and started successfully!") | |
def remove_service(args, service_path): | |
subprocess.run(["systemctl", "--user", "stop", args.name], check=False) | |
subprocess.run(["systemctl", "--user", "disable", args.name], check=False) | |
subprocess.run(["systemctl", "--user", "daemon-reload"], check=False) | |
if os.path.exists(service_path): | |
os.remove(service_path) | |
print("Service removed successfully!") | |
else: | |
print("Service file does not exist.") | |
def main(): | |
home_dir = os.path.expanduser("~") | |
cwd = os.getcwd() | |
parser = argparse.ArgumentParser(description="Manage a user systemd service.") | |
parser.add_argument("command", nargs=argparse.REMAINDER, help="Command to run as a service.") | |
parser.add_argument("--name", help="Service name.", required=True) | |
parser.add_argument("--desc", default="", help="Service description.") | |
parser.add_argument("--workdir", default=cwd, help="Working directory.") | |
parser.add_argument("--rm", action="store_true", help="Remove the specified service.") | |
parser.add_argument("--edit", action="store_true", help="Edit the systemd service file before starting.") | |
args = parser.parse_args() | |
systemd_user_dir = os.path.join(home_dir, ".config/systemd/user") | |
service_path = os.path.join(systemd_user_dir, f"{args.name}.service") | |
if args.rm: | |
remove_service(args, service_path) | |
else: | |
if not args.command: | |
print("Error: You must provide a command to run.") | |
exit(1) | |
create_service(args, service_path, systemd_user_dir) | |
if __name__ == "__main__": | |
main() | |
# vim: set ft=python : |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment