1

I am writing a small daemon which logs the active window name. The relevant part goes like:

import wnck
import gtk

from plugins import IReporter


class ActiveWindowNameReporter(IReporter):

    export_as = 'active_window_name'

    def report(self):
        name = None

        screen = wnck.screen_get_default()
        screen.force_update()
        while gtk.events_pending():
                gtk.main_iteration()

        if screen:
            active_window = screen.get_active_window()

            if active_window:
                name = active_window.get_name()

        return name

I wrote a simple systemd user service file for this:

[Unit]
Description=Activity Monitor Service

[Service]
ExecStart=/usr/bin/python /home/me/Projects/monitor/monitor.py

[Install]
WantedBy=graphical.target

However, running the service fails. In journalctl -r I can see:

Unit actor.service entered failed state.
actor.service: main process exited, code=exited, status=1/FAILURE
ImportError: could not import gtk
import wnck
File "/home/me/Projects/monitor/reporters/active_window_name.py", line 1, in <mod
from reporters import *
File "/home/me/Projects/monitor/monitor.py", line 16, in <module>
Traceback (most recent call last):
detected unhandled Python exception in '/home/tbabej/Projects/actor/actor.py'      
Started Activity Monitor Service.                                                  
Starting Activity Monitor Service...

Seems like the import of gtk module fails because the session is not available? Setting the XDG_SESSION_ID variable in the script did not help though.

2
  • Does it work when started from a terminal inside the graphical session? Mar 15, 2014 at 9:07
  • Yes, it does work.
    – Enuy
    Mar 15, 2014 at 9:16

1 Answer 1

1

System services cannot and should not interact with user sessions. The assumption that there's always exactly one graphical session has never been true on Unix (X11 was multi-user since the beginning), and isn't even true on Windows (after NT 4.0 introduced Terminal Services and XP added Fast User Switching).

In other words, a system service doesn't know which X11 display it should use; doesn't have the right credentials even if you hardcode :0 (only the session's owner knows the right $XAUTHORITY value – being root does not grant any magic powers); and very often will be auto-started before any X11 displays appear, even if you hardcode /home/me/.Xauthority.

This means that scripts like yours must be started inside the graphical session – either through ~/.config/autostart/*.desktop (the XDG Autostart specification), or through ~/.xprofile (a regular shell script).

# ~/.config/autostart/monitor.desktop

[Desktop Entry]
Name=Activity monitor
Type=Application
Exec=nm-applet
3
  • Yes, I was under impression that this would be the case. That's why I was using systemd's user service files (systemd in user mode), e.g. systemd --user start actor.service. Does it make no difference?
    – Enuy
    Mar 15, 2014 at 8:49
  • I haven't noticed this mentioned in your question, sorry. But yes, at this moment, the same still applies. Note that the systemd --user instance itself is started as a system service, [email protected]. This is likely to change in the future (as systemd plans to drop support for multiple graphical sessions for the same user and at the same time start the graphical sessions the themselves via --user). Mar 15, 2014 at 9:06
  • 2
    That doesn't explain why the error is ImportError: could not import gtk rather than GtkWarning: could not open display as would be expected.
    – Dan D.
    Mar 15, 2014 at 9:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .