Python script as systemd service not starting correctly

40 Views Asked by At

I have built a short Python to launch application with my shortcut. It functions normally if I launch it with terminal but I’m trying to apply it as system service to be always on. But I’m encountering error exited, status=203/EXEC and I need help to resolve it. The error I got is code=exited status=203/exec.

This is the code:

from pynput import keyboard
import subprocess

def launch_firefox():
    subprocess.Popen(['firefox'])

def launch_terminal():
    subprocess.Popen(['kitty'])

pressed_keys = set()`
def on_press(key):
    global pressed_keys
    try:
        if key.char == 'q':
            if keyboard.Key.cmd_l in pressed_keys:
                launch_firefox()
    except AttributeError:
        if key == keyboard.Key.enter:
            if keyboard.Key.cmd_l in pressed_keys:
                launch_terminal()
        elif key == keyboard.Key.cmd_l:
            pressed_keys.add(key)



def on_release(key):
    global pressed_keys
    try:
        pressed_keys.remove(key)  # Remove released key from the set
    except KeyError:
        pass

with keyboard.Listener(
    on_press=on_press,
    on_release=on_release) as listener:
    listener.join()`

The service file is:

[Unit]
Description = ...

[Service]
ExecStart=path of interpeter /path of the file.py
Restart=always
[Install]
WantedBy=multi.user.target

I’m on Arch and I’m using Openbox with Xorg.

EDIT: I got this now

ImportError: this platform is not supported: ('failed to acquire X connection: Can\'t connect to display ":0": b
\'Authorization required, but no authorization protocol specified\\n\'', DisplayConnectionError(':0', b'Authorization required, but no authorizatio
n protocol specified\n'))
Mar 06 15:06:15 OSX python3[6722]: Try one of the following resolutions:
Mar 06 15:06:15 OSX python3[6722]:  * Please make sure that you have an X server running, and that the DISPLAY environment variable is set correctl
y
1

There are 1 best solutions below

0
user1686 On

As a general rule, system services do not have access to your graphical environment.

Your graphical login is not omnipresent across the system – this is not Windows 98 anymore, so it's a separate session that's started like any other service (so ordering between services matters), and it's started for your user specifically (so it doesn't even exist until you log in), and there can be more than one (so there is no "default" for a service to use). And of course it has to run as the correct user – you didn't specify User= in your service, so it was running as "root".

It's possible to make it work as a system service, but it is not good practice.

I’m trying to apply it as system service to be always on

You don't need it to be a system service in order to be always-on. You can have it as a user service, or even just a regular non-service autostart app that's started by your desktop every time.

For example, you can put the unit in ~/.config/systemd/user/, changing it to have WantedBy=graphical-session.target (you don't need User= in this case), then start it with systemctl --user start and so on. The per-user service manager does have access to the graphical session (although not immediately, so don't use default.target).

If you really want it to be a system service, it will need to 1) be run as the correct user, 2) have all the environment variables (at minimum HOME, XDG_RUNTIME_DIR, DISPLAY, XAUTHORITY, WAYLAND_DISPLAY...) – which aren't guaranteed to be static, so it's not wise to hardcode their current values in the service, and the list is not exhaustive. When doing this, it would be a good idea to at least do the app-launching through systemd-run --user --service so that the apps inherit the correct environment.