Skip to content
Tags

, ,

My setup for vdr automatic wake up and shutdown

April 14, 2012

Hello

Like all kids, my kids really enjoy watching cartoons. Unfortunately, most of them are broadcast during the morning, sometimes very early in the morning. Since I don’t want my kids to wake up (or wake me up…) too early in the morning to watch cartoon, I record the most interesting programs with vdr (I also edit out commercials before my kids watch them)

To limit my carbon (or equivalent radio-active waste) footprint, I do not want to leave the computer on 24/24, so the machine has to power up by itself before a recording time.

So I’ve setup vdr to automatically setup the wake up time of the computer and shutdown the machine once the recording is finished. Note that this machine is also my main home machine, so it must not shutdown while I’m working on it (typing this blog, for instance).

This should have been easy and fairly documented. Well, it was not that easy. A lot of doc mentions nvram-wakeup which is more or less obsolete. Other docs were in German. So, here’s a summary of the setup so other can benefit from my experience.

First, this was done on a Debian/sid machine, this post should be usable on other distros, provided some adaptations. These adaptations are left as an exercise to the reader (which is marketing lingo for “I don’t have a clue”)

First add this line in /etc/default/vdr:

 ENABLE_SHUTDOWN=1

When vdr has nothing to do, it will run some shutdown scripts, including /usr/share/vdr/shutdown-hooks/S90.custom, which is a link to /etc/vdr/shutdown-hooks/S90.custom.

The output of this script will be eval’ed by vdr, so vdr knows what to do next (e.g. abort shutdown, display a message to user, retry later…).

Here are the possible output of a vdr shutdown script (list taken from vdr-wiki):

  • To abort the shutdown, exit with an errorlevel != 0.
  • If you want a message to be displayed on the OSD when aborting a shutdown,
    then write to stdout:
    ABORT_MESSAGE=<message to display>
  • If you want to defer the shutdown, write to stdout:
    TRY_AGAIN=<minutes to wait before next shutdown request>
  • To overwrite the command that will be executed to shutdown the machine
    after all shutdown hooks have been processed, write to stdout:
    SHUTDOWNCMD=<new shutdown command>
    i.e.:
    echo "ABORT_MESSAGE=\"I do not want to shutdown now!\"" ; exit 1

This script will mess with /sys/class/rtc/rtc0/wakealarm so it must be run as root. But vdr will launch this script and does not run as root. Instead of setting a suid bit, let’s setup sudo to enable this script to gain root privilege from vdr. Add this line in /etc/sudoers (with visudo):

vdr ALL= NOPASSWD: /etc/vdr/shutdown-hooks/S90.custom *

And here’s a commented Perl script that handle the shutdown test:

#!/usr/bin/perl
use IO::File ;
use 5.10.0 ;
use English;
use Path::Class; 

use Sys::Syslog qw(:standard :macros);  # standard functions & macros
openlog('vdr-shutdown', "", "user");

Here’s the call to sudo to gain root privilege (if not already run as root):

if ($EUID) {
    system('sudo','/etc/vdr/shutdown-hooks/S90.custom', @ARGV) ;
    syslog(info => "vdr-shutdown: sudo myself returned $@") ;
}

Get the next timer info from the command arguments provided by vdr:

my ($next_timer,$interval) = @ARGV ;

Setup the next alarm in the mother board:

if ( $next_timer) {
  my $dev_fh = IO::File->new("> /sys/class/rtc/rtc0/wakealarm");
  die "cannot open $dev_fh: $!" unless $dev_fh ;
  my $newtime = $next_timer - 300  ;  # Start 5 minutes earlier
  $dev_fh->print( "$newtime\n" ) ;
  $dev_fh->close ;

  syslog(info => "vdr-shutdown: set wakeup to $newtime") ;
}

Now, let’s check if someone is logged on the system. Weirdly enough, forking a command from this Perl script does not work when it’s run by vdr. Calling the ‘who’ command always return empty. The trick to find if anyone is logged is to check the content of /dev/pts directory. No files in there means that nobody is logged:

my @pts  = dir('/dev/pts')->children;
syslog(info => "vdr-shutdown:  found pts @pts") ;

if (@pts > 1) {
    syslog(info => "vdr-shutdown: retry later: someone is logged") ;
    say 'ABORT_MESSAGE="someone is logged, shutting down deferred"';
    say 'TRY_AGAIN=30'
}
else {
    syslog(info => "vdr-shutdown: nobody is logged, halting") ;
}

Now some cleanup then exit:

closelog() ;

exit 0;

This script has been working for one month, and not a single programs was missed. My kids are happy.

I’m not so happy because I now have a lot of commercials to edit out ;-)

All the best

About these ads

From → computer

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: