11

I have created a --user service in systemd such that a non privileged user can manage a service. This works well. I wanted to restart the service at a fixed given time of day, so i created a cron job in the users crontab.

Strangely this does not work. The user can restart the service if they run:

systemctl --user restart myservice.service

However running this from the crontab does not restart the service. Does anyone know why?

This is running on Ubuntu 16.04.

1
  • Please paste output of command crontab -l. You have to execute it as user which have permissions to this service. The other question is: why do you want to restart it using cron? Commented Oct 10, 2018 at 8:34

2 Answers 2

18

systemctl --user needs to talk to the D-Bus session, which involves setting at least DBUS_SESSION_BUS_ADDRESS and perhaps XDG_RUNTIME_DIR; typically:

XDG_RUNTIME_DIR=/run/user/$(id -u)
DBUS_SESSION_BUS_ADDRESS=unix:path=${XDG_RUNTIME_DIR}/bus
export DBUS_SESSION_BUS_ADDRESS XDG_RUNTIME_DIR
systemctl --user restart myservice.service

You might want to look at systemd timers instead of cron for this.

7
  • 1
    This worked. Thanks. Is there a reason why cron should not be used in this case? Commented Oct 10, 2018 at 8:58
  • 1
    No particular reason, I only suggested timers because they should deal with all this transparently (but I haven’t used timers for user services so I don’t know how to do it and whether it would work). Commented Oct 10, 2018 at 9:00
  • 1
    There is a reason with respect to the larger point made in a question comment. Often in my experience this sort of scheduled externally forced restart is a bodge, that papers over an underlying problem. Commented Oct 10, 2018 at 11:11
  • 1
    systemd user services only run while there is a user session, whereas the cronjob would probably still run if there’s no user session. (That’s why the cronjob doesn’t know about the dbus session: cron exists outside of the session.) I agree that a systemd timer is the better solution here. Commented Oct 11, 2018 at 12:50
  • 1
    @Seamus in a shell script run from the user’s crontab. Commented Apr 27 at 16:52
0

This may be considered a bit of a "hack", but FWIW:

I was slightly bothered by the fact that I had to add the "D-Bus environment" stuff from Stephen's excellent and correct answer to my script. So I'll propose another method that gets access to the "D-bus environment" as follows:

Open the root crontab, and add one line:

$ sudo crontab -e

# in the editor, add this line: 

20 18 * * * su <user> -l -c </path/to/script>
# for example:
00 12 * * * su pi -l -c /home/pi/some_script.sh 
# --OR--
@reboot su pi -l -c /home/pi/some_script.sh

Where some_script.sh contains one or more calls to :

systemctl --user <action> <servicename> 

What's going on:

  • su means "run a command with/as a substitute user ..." (ref man su)
  • pi is just the name of an unprivileged user
  • -l start shell as a login shell (where the "D-Bus environment" is loaded)
  • -c pass the following command to the shell (in this case /home/pi/some_script.sh)

Why am I "bothered"?:
Maybe a personality quirk, but it seems to me that all software coming from RedHat is... "unconventional" (e.g. systemd, D-bus, etc)

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.