16

I'm trying to learn systemd services by trying to start xclock as a service; the service file is below

[Unit]
Description=clock

[Service]
Environment=DISPLAY=:0
ExecStart=/usr/bin/xclock

[Install]
WantedBy=graphical.target

Any ideas what's wrong here? I'm getting an error saying "cannot connect to display."

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
dogs
  • 163
  • 1
  • 1
  • 4

3 Answers3

25

An application needs two things to open a window on an X display. It needs to know the location of the X display; that's conveyed by the DISPLAY environment variable. It also needs to authenticate with the X server. This is conveyed through a cookie, which is a secret value generated by the X server when it starts and stored in a file that only the user who started the X server can access. The default cookie file is ~/.Xauthority.

If your X server is using the default cookie file location, then adding Environment=XAUTHORITY=/home/dogs/.Xauthority will work (assuming /home/dogs is the home directory of the user who is logged in under X). If you need to find the location, see Can I launch a graphical program on another user's desktop as root? and Open a window on a remote X display (why “Cannot open display”)?

Alternatively, running the program as the user who is running the X server will work, provided that the cookie file is in the default location (if not, you'll have to locate the cookie file, like in the root case). Add the User directive (e.g. User=dogs).

Of course the service won't run if there isn't an X display by that number owned by the user you specify.

It's rather bizarre to start a GUI program from Systemd. It wasn't designed for this. GUI programs live in an X session, started by a user. Systemd is for system processes. You should experiment with daemons instead.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
  • 2
    It's not a problem using `systemctl --user`. Also the `DISPLAY` variable is not a matter then. Have a look [here](https://unix.stackexchange.com/a/519585/105615). – Suuuehgi May 17 '19 at 21:24
  • Having the same issue, where I'm trying to auto-magically boot into X with a Chromium configured in `--kiosk` mode. We are building a Kiosk-like product which should always boot up into full screen mode with the web app fully loaded. I've seen cases where it works perfect and other times it had issues (like a race condition of some sort). – Jeach Jun 05 '20 at 15:16
  • This might also help if there is no graphical-session.target: https://superuser.com/a/1128905/683326 – gschenk Jun 18 '20 at 17:22
  • On newer versions of Ubuntu/GDM, the Xauthority file is found here: `/run/user//gdm/Xauthority`. – Alexis Wilke Nov 04 '20 at 20:17
  • can't find Xauthority in linux mendel os – Bhanuchander Udhayakumar Feb 25 '21 at 13:21
  • @BhanuchanderUdhayakumar Gdm likes to put it in different places. Check `echo $XAUTHORITY`. If that doesn't help, ask a new question. I know nothing about mendel os. – Gilles 'SO- stop being evil' Feb 25 '21 at 15:02
2

A modern way (in 2021) is not to hard code the environment within the .service unit file. Instead, do something like this:

$ cat /etc/X11/xinit/xinitrc.d/50-systemd-user.sh
#!/bin/sh

systemctl --user import-environment DISPLAY XAUTHORITY

if command -v dbus-update-activation-environment >/dev/null 2>&1; then
    dbus-update-activation-environment DISPLAY XAUTHORITY
fi

This is what is done in Arch Linux, for example.

Explanation: When starting X11, both the DISPLAY and the XAUTHORITY environment variables are inherited for all systemd user service unit files (i.e. those managed by systemd --user).

One could check those are properly set by running systemctl --user show-environment.

By doing so, you don't need to use Environment= directives in your .service files.

thiagowfx
  • 1,221
  • 11
  • 20
-2

You can add in .xinitrc :

xhost si:localuser:$USER

It works for me!

GAD3R
  • 63,407
  • 31
  • 131
  • 192
Monica
  • 1