Does cron wake up my computer?

I need to start a Python script every day at midnight, and after some searching on the internet, I found out, that I can use cron for that. What I am curious about is, that if I schedule a cron task for midnight, will it wake up my computer to do the job? Or do I have to wake up the computer using something else? I am using Ubuntu 16.04.


Solution 1:

Short answer:

No.

You can however use rtcwake. With rtcwake, you can wake up the computer, set it up to run commands and scripts afterwards etc.

Options include both waking up at an absolute time, as well as waking up at a specific time span from now:

-s seconds | --seconds seconds
    Sets the wakeup time to seconds in future from now. 
-t time_t | --time time_t
    Sets the wakeup time to the absolute time time_t. time_t is the time in seconds since 1970-01-01, 00:00 UTC. Use the 

An example of how rtcwake can be used is in this answer.
See also, as always, man rtcwake

Solution 2:

There is already an answer mentioning that you can use rtcwake for this purpose, I would like to elaborate a bit more on how you can do it.

Prerequisites

First, install rtcwake (from the util-linux package), dmidecode and anacron:

sudo apt install util-linux dmidecode anacron

Check whether your computer can wake up from standby mode:

sudo rtcwake -m mem -s 30

This should put your computer to standby mode and wake it up 30 seconds later. (I picked 30 seconds because suspending or hibernating your computer can take some time, and if the wake-up time ends up being earlier than the end of the standby process, the wake-up may not work.)

You can try other standby methods than mem, disk in particular allows greater power saving but encrypted systems won't be able to resume from it without manually providing the password.

If your computer woke up successfully, check whether it is possible to determine the reason of the wake-up:

sudo dmidecode | grep "Wake-up Type"

If you see Wake-up Type: APM Timer in the output, you are good to go.

A custom script for suspending

If all the prerequisites are met, we can put together a simple script that does the following:

  • Suspends the computer while setting a wake-up time as well.
  • After wake-up, checks whether the wake-up was scheduled or manual.
  • If wake-up was scheduled, executes the cron jobs and puts the computer back to standby, setting a new wake-up.

Here is the script:

#! /bin/bash
# https://askubuntu.com/a/1323317
while true
do
  wake_at=22:05 # Set to whenever you want the cron jobs to run each day
  wake_ts="$(date -d "$wake_at" +%s)"
  now_ts="$(date +%s)"
  if [ "$wake_ts" -lt "$now_ts" ]
  then
    wake_ts="$(date -d "tomorrow $wake_at" +%s)"
  fi
  rtcwake -m mem -t "$wake_ts"

  # After wake-up
  #
  # Without this sleep, the current time would still seem to be the instant when
  # the suspend happened, confusing man and machine alike.
  sleep 1
  if dmidecode | grep -q "Wake-up Type: APM Timer"
  then
    # We trigger anacron manually. To prevent cron jobs from running during
    # active uptime, its systemd triggers need to be disabled.
    /usr/sbin/anacron -nd
  else
    exit 0
  fi
done

This script needs to be executed as root, so I recommend setting the root user as the owner and using sudo for starting it. You can use the sudoers mechanism to make it possible to run it without entering a password, but I won't elaborate on that here as it is already described in a lot of guides.

To make this mechanism easier to use, I recommend setting a hot-key in your desktop environment. If you do that, you should use a wrapper script that instructs your desktop-environment-specific screen-saver command to lock the screen before it executes the script above with sudo.

Disabling normal schedules

If you want cron jobs to only run at the scheduled wake-up times and not during the active uptime of the computer, you need to disable their existing schedules. On Ubuntu, cron jobs are organized in directories but those directories are executed by lower-level jobs in /etc/crontab:

25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

You can see that the crontab entries that run daily, weekly and monthly jobs are only executed if anacron is not installed (with the intent that anacron takes over the task of executing them otherwise). Since we just installed anacron, cron won't run these jobs automatically any more, but anacron will, which we need to disable.

Anacron itself is also a scheduled task triggered by systemd. In order to disable it, issue:

sudo systemctl mask --now anacron.service
sudo systemctl mask --now anacron.timer

Instead of mask, disable may be sufficient, I found conflicting information about this on the internet, but mask may help preventing a package upgrade from re-enabling the disabled items.

Once this is done, the daily, weekly and monthly cron jobs will not get executed during the normal uptime of the computer, only by the suspend script provided above and only after scheduled wake-ups.