On my desk I have a full-size PC running Linux that I use for most of my work. I much prefer it to working on a laptop. What I don’t like so much is the increased power consumption, so I’ve set the computer to go to sleep after a fairly short period of inactivity.

I’m using the Gnome desktop, so detecting inactivity and initiating sleep is handled by Gnome. This will be relevant later.

I also want to run a backup every day. Ideally, I want that to happen when I’m not using the computer. However, when I’m not using the computer it’s asleep and therefore unable to run any jobs.

Here’s how I solved that.

First, I have a root cron job set to run once an hour from 07:00 to 23:00. This schedules the motherboard’s real-time clock to wake the computer at 03:00 the next morning.

By running once an hour, I ensure that on any day that I’m using my computer, it will be woken early the next morning for a backup. As this always sets the wake-up time to tomorrow, I don’t want it to run if I happen to be at the computer after midnight, but the 07:00 to 23:00 range is safe.

This scheduling is accomplished with the rtcwake command, found in the util-linux package on Ubuntu, and using date to compute the wake-up time.

0 7-23 * * * /usr/sbin/rtcwake --mode no --time $(date +\%s -d 'tomorrow 03:00')

Second, in my user crontab, I schedule my backup script to run at 03:02, shortly after the computer wakes up.

2 3 * * * /home/paul/bin/backup.sh

Third, in my backup script I make sure that the computer doesn’t go to sleep while the backup is running by using the gnome-session-inhibit command. As this script is running from cron, we need to find and set the D-Bus session explicitly. The app-id setting is arbitrary; I’ve chosen something usefully descriptive.

The script runs itself inside gnome-session-inhibit via a short stanza at the top.

set -o errexit
set -o nounset
set -o pipefail

if [ -z ${SESSION_INHIBITED+x} ]; then
  export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"

  gnome-session-inhibit --app-id NightlyBackup $0
  exit $?

# Real backup task continues here

I wouldn’t recommend this for a laptop that might end up cooking itself in a bag, but for a desktop it works well.