Sunday, March 29, 2015

Prevent suspend/hibernate if system is remotely backed up via rdiff-backup

I usually use rdiff-backup to backup several of my systems. One is a workstation which goes to sleep after some time of idling around. Now having a user logged in running rdiff-backup (or rsync, rsnapshot etc for that matter) won't prevent the system from being put to sleep. Naturally this happens before the backup is complete. So some time ago I was looking for a resolution and recieved a suggestion to use a script in /etc/pm/sleep.d/. I had to modify the script a bit, because the query result always was true. So this is my solution in /etc/pm/sleep.d/01_prevent_sleep_on_backup now:

#!/bin/sh

. "${PM_FUNCTIONS}"

command_exists rdiff-backup || exit $NA

case "$1" in
        hibernate|suspend)
                if ps cax | grep -q rdiff-backup
                then
                        exit 1
                fi
        ;;
esac

exit 0

Currently testing ...

Update

The above works with pm-utils; but it fails with systemd. Seems I have to move and modify the script for my system.

Update 2

It doesn't work. In short: exit 1 doesn't prevent systemd from going to suspend. I can see, that the script itself leads to the results I want, so the logic is correct. But I cannot find a way to tell systemd, to stop suspend. Shouldn't it be doing this automtically in a case, where a remote user is logged in and runs a command?

Update 3

There is also a related bug report.

9 comments:

  1. Look at using `pgrep` for finding the process instead. Piping `ps` to `grep` can be finicky, reporting itself as a match due to race conditions and such (leading to `ps ax | grep -v grep | grep process` and similar error-prone constructs).

    ReplyDelete
  2. See `man systemd-sleep` for the info about scripts in the /lib/systemd/system-sleep/ in order to convert the script here to one that will work on logind systems. (if you are using those systems)

    ReplyDelete
    Replies
    1. Yeah, I found recently, that with systemd a different approach is required :( Is the script supposed to be put under /lib/systemd/system-sleep/ only or is there a directory in /etc too?

      Delete
    2. There seems to be no /etc equivalent, so just make sure to prefix the script with local- or something like.

      Delete
  3. Just run your process under systemd-inhibit, which will prevent the system from suspending while the process is running. When the process completes, assuming the conditions still indicate that a suspend is warranted (for instance, the lid is closed), the system will immediately suspend.

    ReplyDelete
    Replies
    1. Hi Josh. I'm backing up a system over SSH. So using systemd-inhibit the command on the backup-server probably should be something like this: "rdiff-backup [..] --remote-schema 'ssh -C %s /usr/bin/sudo /bin/systemd-inhibit [..] /usr/bin/sudo /usr/bin/rdiff-backup --server [..]' [..]". I would need to give the backup user sudo permission for systemd-inhibit too and change his .ssh/authorized_keys file, which currently holds a command string. I really don't like this idea. Is there no way to generally disable suspend/hibernate/sleep as long as a user is logged in? JFTR: There is probably a related bug report for backupninja (#771641).

      Delete
    2. As far as I know, you don't need special permissions to run systemd-inhibit (beyond being a logged-in user and running in a session that includes pam-systemd).

      Delete
    3. As Josh said, systemd-inhibit can be run by users in a session by default. It is controlled by the org.freedesktop.login1.inhibit-block-sleep action policy, declared on my system in /usr/share/polkit-1/actions/org.freedesktop.login1.policy.

      Also, if you are using IdleAction in logind.conf for this suspend-on-idle functionality, the logind.conf(5) man page suggests that the key to prevent needless idle action is to correctly report active sessions. However, it's not very clear what they mean by that.

      Delete
  4. @Josh, systemd-inhibit sounds great. Will use this for my backup-script. Thank's a lot :)

    ReplyDelete