Wake Up Linux With an RTC Alarm Clock

Most Linux users know how to set scheduled automatic shutdowns using cron. Did you know you can also set automatic wakeups? Most motherboards built after 2000 support real-time clock (RTC) wakeups, so you can have your computer turn itself on and off on a schedule.

BIOS Wakeup

One way to wake up your computer at a scheduled time is to enter your computer's BIOS and set a wakeup alarm in the Power Management settings. This will be managed either by APM or ACPI settings, depending on the age of your BIOS and any modifications made by the motherboard manufacturer. APM, Advanced Power Management, is an older power management standard. ACPI, Advanced Configuration and Power Interface, is the newer, more advanced standard. Chances are you'll see both. Look for a setting to set the date and time for wakeups. If this does what you need, you're done and can go read something else now. On my main workstation it's limited and only schedules one wakeup event per day, and it won't let me schedule weekdays only. So this is a job for Linux itself.

 

Joseph Chamberlain Memorial Clock Tower, tallest clock tower in England. Image courtesy Wikimedia Commons

 

Kernel Support

If you have any scheduled wakeups set in your BIOS, remove them, and then verify your system has all the necessary pieces in place. This how-to is for kernel versions 2.6.22 and later; run uname -r to see your kernel version. Your Linux kernel should already have everything you need, unless you or your distribution maintainer have removed RTC support. So check your kernel configuration file, like this example:

$ grep -i rtc /boot/config-3.2.0-23-generic 
CONFIG_HPET_EMULATE_RTC=y 
CONFIG_PM_TRACE_RTC=y 
CONFIG_RTC_LIB=y 
CONFIG_RTC_CLASS=y 
CONFIG_RTC_HCTOSYS=y 
CONFIG_RTC_HCTOSYS_DEVICE="rtc0" 
[...]

That returns a couple dozen lines of output showing full RTC support. Another way is to check your system log. The syslog is configured a little differently on various distros, so one of these two examples should work:

# grep -i rtc /var/log/messages 
$ grep -i rtc /var/log/kern.log

And then you should see several lines of useful output like this:

 Nov 24 07:17:27 studio kernel: [0.248407] RTC time: 15:17:15, date: 11/24/12
 Nov 24 07:17:27 studio kernel: [1.692667] rtc_cmos 00:03: RTC can wake from S4
 Nov 24 07:17:27 studio kernel: [1.692762] rtc_cmos 00:03: rtc core: registered rtc_cmos as rtc0
 Nov 24 07:17:27 studio kernel: [1.692789] rtc0: alarms up to one month, y3k, 114 bytes nvram, hpet irqs
 Nov 24 07:17:27 studio kernel: [1.713143] rtc_cmos 00:03: setting system clock to 2012-11-24 15:17:17 UTC (1353943037)

This example shows that the RTC is set to Coordinated Universal Time (UTC), which is desirable because then you don't have to hassle with daylight savings time. (I love how we can change time itself, instead of adjusting our schedules.) rtc0 is the clock's device name, which is standard because it would be unusual to have more than one RTC.

Simple Wakeup Test

Now let's get to the fun part and do a simple manual wakeup test. First check if any wakeups are set:

$ cat /sys/class/rtc/rtc0/wakealarm

No value returned means no alarms are set. These two commands reset the alarm to zero, and then set a wakeup alarm three minutes in the future:

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

Now when you run cat /sys/class/rtc/rtc0/wakealarm you should see a value similar to 1354037019. This is the Unix epoch time, which is the number of seconds since UTC midnight 1 January 1970. You need to see a value here to verify that a wakeup time has been set. Next, shutdown your computer and wait for it to start. If this simple test succeeds you are ready to use this simple shutwake script to shutdown and start up your computer whenever you want:

#!/bin/bash 
sh -c "echo 0 > /sys/class/rtc/rtc0/wakealarm" 
sh -c "echo `date '+%s' -d '+ 420 minutes'` > /sys/class/rtc/rtc0/wakealarm" 
shutdown -h now

It works like this: make it executable, put it in root's path (like /usr/local/bin), and create a root cron job to run it when you want your computer to shut down, like this example that runs the script at five minutes past midnight on weeknights:

# crontab -e 
# m h  dom mon dow   command 
05 00 * * 1-5 /usr/local/sbin/shutwake

The script will set the wakeup alarm at 420 minutes after shutdown at 12:05AM. This is a lot simpler than hassling with UTC and epoch time conversions, which is what you'll see in other RTC wakeup howtos. You can easily create multiple shutdown and wakeup times by creating different crontabs and modifying the number of minutes in the wakeup alarm.