Running an X application from a shell script via systemd timer

I’m trying to create a systemd (user) timer that opens certain tabs every day at 9PM with xdg-open. Here are the files:

/home/me/.config/systemd/user/test.service

[Unit]
Description=Test

[Service]
Type=simple
Environment=DISPLAY=:0
ExecStart=/bin/bash /home/me/test.sh

/home/me/.config/systemd/user/test.timer

[Unit]
Description=Test Timer
RefuseManualStart=no
RefuseManualStop=no

[Timer]
Persistent=true
OnCalendar=*-*-* 21:00:00

[Install]
WantedBy=timers.target

/home/me/test.sh

#!/bin/bash


websites=(
    "http://unix.stackexchange.com/"
    "http://stackoverflow.com/"
)

for i in "${websites[@]}"
do
    # works with /usr/bin/firefox
    /usr/bin/xdg-open "$i"
done

This doesn’t open anything.

When I replace xdg-open with firefox in the above file, the tabs get opened. However, when I execute xdg-open "http://unix.stackexchange.com/" in a terminal it opens a tab in Firefox.


systemctl --user start test.service 
systemctl --user status test.service 

prints:

● test.service - Test
   Loaded: loaded (/home/me/.config/systemd/user/test.service; static; vendor preset: enabled)
   Active: inactive (dead)

Jun 29 15:06:59 me-PC systemd[1513]: Started Test.

How can I make this timer work with xdg-open?

Answer

Often differences between running a script manually and running it via systemd are due differences in the environment. Before the xdg-open call, add the command env on it’s own line, which dumps the environment.

Now run the test manually and via systemd. Look for other variables besides DISPLAY that could be causing the difference. By continuing to add environment variables into the systemd script, you should be able to find the ones systemd needs to make this work.

Your bash code in your test looks fine, but here’s a revision that’s a bit more idiomatic if you are interested. bash naturally splits on space and URLs don’t contain space, so this alternate code works. I’ve also replaced do/done with braces:

websites="
    http://unix.stackexchange.com/
    http://stackoverflow.com/"

for i in $websites; {
    # works with /usr/bin/firefox
  /usr/bin/xdg-open "$i"
}

Leave a Reply

Your email address will not be published. Required fields are marked *