Skip to content

Instantly share code, notes, and snippets.

@redraw
Created March 3, 2025 17:44
Show Gist options
  • Save redraw/4f2d5bd7d98bc23e3ccf5d8542e187ca to your computer and use it in GitHub Desktop.
Save redraw/4f2d5bd7d98bc23e3ccf5d8542e187ca to your computer and use it in GitHub Desktop.
#!/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