15

I have this cronjob set :

* * * * * /usr/bin/systemctl suspend

And it is not working. But I can run it in a shell and it works. I don't understand what could be not working.

EDIT Redirecting error output to /tmp/error gives this :

Failed to issue method call: Access denied
Failed to issue method call: Access denied

My question is then : Are cronjobs run as a special user (cron for example), which would explain that my user can run the command, but not cron itself?

Additional explanation :

  • This is a minimal example to show a problem I have in a script (that makes more sense than the single command provided here)

  • systemctl is part of systemd. I think reboot, shutdown, suspend are working with a non-root user with systemd. Anyway, it is working on my system.

  • Finally, I use Arch Linux and /bin, /usr/sbin, /sbin are all symlinks to /usr/bin.

Gradient
  • 3,659
  • 1
    What exactly are you trying to do here? What does the command do when you run it in the shell? – terdon Sep 16 '13 at 01:08
  • It suspends my computer – Gradient Sep 16 '13 at 02:01
  • And do you want that to happen every minute? Your systemctl is in /usr/bin and it accepts suspend like that? What *nix are you using? – terdon Sep 16 '13 at 02:02
  • 1
    No, it is an example. It is actually in a script that suspends when battery power is low. But this is the part in my script that is not working. I tried to give a minimal example of the problem (even if this seems to make no sense). – Gradient Sep 16 '13 at 02:06
  • I am using Arch linux and /bin, /sbin, /usr/sbin are all symlinks to /usr/bin. – Gradient Sep 16 '13 at 02:08
  • 2
    OK,since this question is collecting close-votes, please [edit] it to add this extra info. Your distro is important (systemctl suspenddoesn't work on Debian or RedHat distros) and so is explaining that you don't actually want to do what you're showing :). Also, try adding 2> /tmp/error or something to capture any errors you might be getting. Finally, tell us which user is running this crontab. – terdon Sep 16 '13 at 02:11

6 Answers6

7

I can't really answer as such but I think I can point you in the right direction. I found this in the Arch Wiki page of systemd:

polkit is necessary for power management. If you are in a local systemd-logind user session and no other session is active, the following commands will work without root privileges. If not (for example, because another user is logged into a tty), systemd will automatically ask you for the root password.

[list of various systemctl commands]

systemctl suspend

This suggests to me the following possibilities:

  1. You have another user logged in. Perhaps you have logged in via a tty?

  2. cron runs its commands using /bin/sh. By default, on Arch this is a symlink to /bin/bash. This would mean that cron is starting a non-interactive bash shell which then detects that there is another user session running (yours), so it does not have the right to run systemctl despite running as your user.

So, if your problem is because cron is not allowed to run systemctl because you are already logged in, you might be able to get around that by playing with polkit but I have no experience there so I can't help.

terdon
  • 242,166
  • Thank you! The first option can be eliminated as I am able to execute the command in a shell. But I will do some more research about the second option. – Gradient Sep 16 '13 at 04:29
  • @Gradient did you discover how to fix this? I'm struggling with the same problem. – AkiRoss Feb 16 '15 at 01:50
  • Could you please explain the second possibility in more detail ? Is there any way to confirm that this is indeed the problem ? I executed w and uptime from the scripts run by cron. Their outputs indicated the there was only user. So, does this mean that there is some other problem ? – Anmol Singh Jaggi Jun 11 '16 at 08:29
3

An easy workaround is to use root's crontab instead of your own. Edit it with:

$ sudo crontab -e

instead of:

$ crontab -e
Michael Mrozek
  • 93,103
  • 40
  • 240
  • 233
2

There is a much easier solution without sudo, by using systemd-run:

The important thing is that you have to set/export the DBUS_SESSION_BUS_ADDRESS environment variable for the related user. Simply create a script named systemctl-suspend or something, with the following lines:

#!/bin/bash
# This is a workaround script to be able to use 'systemctl suspend' in user-cron
PATH=/usr/bin
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/"$(id -u "$LOGNAME")"/bus
systemd-run --user systemctl suspend

and make it executable, then copy that script file to a folder such as /usr/local/bin.

Finally, start the script in the user's crontab just like this:

0 22 * * * /usr/local/bin/systemctl-suspend

Tested on Debian 10 (buster).

Pablo A
  • 2,712
1

Quoting from here:

The other answer is great! But it requires root cron.

If you want to hibernate from non-sudo cron, there are 2 options:

1. Using polkit

Make a file containing the following:

[Enable hibernate to be run via cron]
Identity=unix-user:*
Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.hibernate-multiple-sessions
ResultAny=yes 

named com.0.enable-hibernation-from-cron.pkla in the directory /etc/polkit-1/localauthority/50-local.d/.

Explanation is given here.

2. Using visudo

Quoting from here:

If users should only be allowed to use shutdown commands, but not have other sudo privileges, then, as root, add the following to the end of /etc/sudoers using the visudo command.

user hostname =NOPASSWD: /usr/bin/systemctl poweroff,/usr/bin/systemctl halt,/usr/bin/systemctl reboot
<p>Substitute <code>user</code> for your username and <code>hostname</code> for the machine's hostname.<br>
Now your user can shutdown with <code>sudo systemctl poweroff</code>, and reboot
with <code>sudo systemctl reboot</code>. Users wishing to power down a system can
also use <code>sudo systemctl halt</code>.<br>
Use the NOPASSWD: tag only if you do not want to be prompted for your password.  </p>

In my case, the exact line is:

anmol ALL=NOPASSWD: /bin/systemctl hibernate

(Note that the location of systemctl might be different on your system.)

After this, you can write sudo systemctl hibernate fron cron to hibernate.

Note: Directly modifying /etc/sudoers is bad; instead make a custom sudoers file under /etc/sudoers.d/ using the command - sudo visudo -f /etc/sudoers.d/custom.

1

If you're using the system crontab, then you forget the user field. Try:

* * * * * root /usr/bin/systemctl suspend
  • Are you sure there is a user field? I have never seen a cronjob with it before. Anyway, the command works when I run it as a user in a shell. – Gradient Sep 16 '13 at 02:07
  • 3
    @Gradient there is a user field if you are using /etc/crontab, is this a crontab you created with cron -e as your normal user? – terdon Sep 16 '13 at 02:45
  • It is a crontab I created with crontab -e as a normal user. – Gradient Sep 16 '13 at 02:49
  • your normal user account probably doesn't have permission to run systemctl suspend without sudo. – cas Sep 16 '13 at 03:17
-2

You need use systemd config file in /etc/systemd/system

[Unit]
Description=Pimcore Events Processor

[Service]
WorkingDirectory=/var/www/html
ExecStart=/usr/bin/php run something
Restart=always
WatchdogSec=300 #in seconds
User=www-data
Group=www-data

[Install]
WantedBy=multi-user.target
James M
  • 129