ecocron - a green scheduler

This short article addresses the following challenge: you are away from your computer and have a task, mytask, that you want to run say every day at 11 pm. Additionally, in a planet-friendly spirit (or in a money-saving one), you would like your computer to be off during the time the task is not running.

This challenge can be divided into three compartments:

  1. scheduling the task
  2. scheduling hibernation
  3. scheduling waking up

Scheduling mytask

In some situations, you may consider delegating the automated execution of mytask to an online scheduler, aka a webcron. This is the case, for example, when the task can be hosted on a webserver accessible via a URL.

Otherwise, for local tasks, or for ones you want to schedule on a remote shell account, traditional softwares include the historical cron or anacron programs. On another hand, fcron is a powerful and flexible scheduler. A task which should take place daily at 11 pm is easily configured in a fcrontab like:

#executes mytask every day at 23:00
0 23 * * * mytask

Of course, more advanced scheduling is possible, see fcrontab's manual.

Scheduling hibernation

Once the daily task is completed, you would like the computer to hibernate. According to the ACPI specification, the following four Global "Gx" states and six Sleep "Sx" states exist for an ACPI-compliant computer system:

In practice, the kernel can be asked to put the computer into one of the G1 substates through programs like swsusp/Suspend2/TuxOnIce, uswsusp, or pm-utils. Hence, it seems natural to implement the requirement to hibernate after mytask with something like:

#executes mytask then sleeps (s2ram) every day at 23:00
0 23 * * * mytask; sudo /usr/sbin/pm-suspend

Alternatively it is possible to set the computer to hibernate at a fixed time. In the following example, mytask is given a timeout of 5 minutes.

#executes mytask every day at 23:00, sleeps (s2ram) every day at 23:05
0 23 * * * mytask
5 23 * * * sudo /usr/sbin/pm-suspend

Scheduling waking up

Of course, with the above fcrontab, mytask will be run only once, and the system will then sleep forever. The reason is that so far, nothing wakes it up. MythTV explains how the ACPI wake up works.

Information about the Real Time Clock (RTC) can be displayed with:

cat /proc/driver/rtc

From kernel 2.6.22, the wake up time is stored in /sys/class/rtc/rtc0/wakealarm.

ls /sys/class/rtc/rtc0/wakealarm

Instead of accepting a formatted time, wakealarm accepts the number of seconds since Jan 1, 1970 (this is known as "unix time", "POSIX time" or "epoch time"). It is good that your BIOS clock is set to UTC time - not localtime - otherwise it will wakeup at the wrong time. However, it is still possible if the BIOS clock is set to localtime. If you want to change the wakealarm time, you will need to write the new wakealarm time to the BIOS.

To manually test the wakealarm (wake the machine 5 minutes from now):

sudo sh -c "echo `date '+%s' -d '+ 5 minutes'` > /sys/class/rtc/rtc0/wakealarm"
cat /sys/class/rtc/rtc0/wakealarm

To check that the wakealarm is correctly stored:

cat /proc/driver/rtc

UTC and local time can be source of trouble with the hardware clock and fcron, especially if a task needs to be run while the system is asleep. See man hwclock and the fcron FAQ for potential help.

The idea is then to update the wakealarm for the next day after mytask has been run, then go to sleep.

#executes mytask every day at 23:00, and sets the new wakealarm to the next day 22:55 then sleeps (s2ram) at 23:05
0 23 * * * mytask
5 23 * * * sudo sh -c "echo `date '+%s' -d '+ 23 hour 50 minutes'` > /sys/class/rtc/rtc0/wakealarm"; sudo /usr/sbin/pm-suspend

As usual, critics and suggestions are welcome.

Little Neo, Juin 2012