Installing BackupPC on OpenWRT
I wanted to have a backup server for my church that would automatically take backups when computers came on to our new wireless network. BackupPC immediately sprang to mind, but it only runs on Linux. How could I get a Linux server into the church in a very low cost way? Answer: An Asus wireless router running OpenWRT.
Hacker Alarm Clock
I was at the ELCA Central States Synod Candidacy Retreat with my wife last night, and we realized far too late that we lacked a travel alarm clock. Also lacking an internet connection, it was impossible to download an alarm clock program from the Ubuntu apt repositories. Instead, I quickly coded up this Hacker Alarm Clock in perl. It sounds just like the alarm clock we have at home! Who says that you can’t use a Computer Science degree in ministry? If you can think of other approaches, post them in the comments.
#!/usr/bin/perl
my $s = time();
my $e = $s + (3600 * .005);
print "Starting at: $s\n";
while (time() < $e) {
print "Ending at: $e (".($e-time())." secs from now)\n";
sleep 5;
}
print "Press Control-C (or Mute) to turn off alarm.\n";
open( DSP, '>', '/dev/dsp' );
while (1) { print DSP (\001 x 150); sleep 1; }
Template Toolkit: how to generate static HTML on any path
My company generates our website using Template Toolkit‘s ttree tool. We want our site to be built with absolute paths in the HTML, so we need to be able to accomodate that with file:// URLs when we test it. We use code like this:
The script to invoke ttree in our testing environment:
#!/bin/bash
cd `dirname $0`
rm -r ./out_test/*
ttree -a --relative --pre_process=./lib/config.test \\
--pre_process=./lib/config.common \\
--define basedir=`pwd` \\
-f ./lib/ttree_test.cfg
In lib/config.test:
[% root = 'file://' _ basedir _ '/out_test' %]
In lib/config.deploy (when we build for production):
[% root = 'http://www.ideaworks.com/' %]
This way, rather than hard-coding the testing path in lib/config.test, it Just WorksTM.
The Value of Community, or Why I Love Perl
I’ve been asked a number of times recently why I chose to use Perl to develop SAGrader, my company’s flagship essay grading product. I’ll be the first to admit that Perl tends to permit bad (unreadable, unmaintainable, overly terse) code in more ways then, say, Java. I think that those problems are mitigated by keeping to modern best practices in Perl and adhering to a coding standard, but that’s not why I love Perl. I love Perl because of the community.
SAGrader, for example, is only implemented in about 40,000 lines of code, split between actual application code, unit and acceptance tests, and HTML templates. That’s all! But if you ruthlessly reuse code from CPAN, the hub of the Perl community, you can implement computationally intelligent essay grading, a complete website to handle thousands of students, and everything else that goes on behind the scenes to make a website like SAGrader work in very little code and time. While SAGrader may only be 40,000 lines of code, we reuse almost a million lines of Perl from CPAN.
The downside of this much code reuse is that it increases the resident size of your program in memory. Frankly, memory is cheap, and programmer time, effort, and happiness is not. Perl might not be the best tool for every job, but for this job, it’s saved us (without exaggerating) man-years of time and effort.
Using next_successor with Graph::Traversal
I recently needed to do a graph traversal using the excellent perl Graph library, but I needed to determine the order for visiting new nodes in the fringe myself. Graph::Traversal provides a next_successor attribute which takes a code ref so that you can specify this behavior yourself. Unfortunately, in version 0.80 that feature isn’t well documented, and if you try to use it, you get an “unknown attribute” error. I’ve submitted a patch to enable, document, and test the feature. Now, if you want (for example) to do a breadth-first traversal, but visit the nodes in reverse alphabetical order, you can do this:
Graph::Traversal::BFS->new(
first_root => 'a',
pre => sub { print $_[0]; }
next_successor => sub { (reverse sort keys %{$_[1]})[0]; },
)->bfs;
Dynamic CSS/JS/HTML in Template Toolkit wrappers
I’ve been asked about this a few times on #tt, so I thought I’d provide it for future Googlers. If you’re looking to optionally include certain files in a Template Toolkit wrapper, it’s very easy. You just provide the file names as a parameter to the WRAPPER call.
First, the wrapper file itself, wrapper.tt:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>[% title %]</title>
<body>
[% IF includes %]
<div id="sidebar">
[% FOREACH include_file = includes %]
[% INCLUDE $include_file %]
[% END %]
</div>
<div id="content">
[% ELSE %]
<div id="wide_content">
[% END %]
[% content %]</div>
</body>
</html>
And then you call the file like this:
[% WRAPPER wrapper.tt
title = 'My Title'
includes = [
'includedfile1.tt',
'includedfile2.tt'
]
%]
<h1>Content for middle</h1>
[% END %]
It’s pretty straightforward to adapt this to CSS or JS files, or whatever you need to customize in the wrapper.
Debugging long-running perl programs in Debian
One of the slicker ways I’ve seen of trying to figure out what Perl is doing in a long-running process is defining a signal handler, like so:
use Carp ();
$SIG{‘USR2′} = sub {
Carp::confess(“Caught SIGUSR2: Dumping stacktrace and dieing:”);
};
It works great, dumping the current stacktrace to STDERR. But if you’re stuck in a loop inside the perl interpreter, that user-level signal is never handled, and you don’t get anything. Foiled again! You’re going to have to use (gasp!) the GNU debugger (gdb).
While the advice offered in Debugging mod_perl and Debugging mod_perl C internals is useful, most of the magic with gdb doesn’t work unless you are running a perl with debugging symbols on. How do you get that in Debian-based distributions?
sudo aptitude install perl-debug
Then run the process:
/usr/bin/debugperl path/to/program.pl
Attach gdb:
gdb
attach Process ID
Define the curinfo gdb macro. (see Analyzing the Core File.) If you see “my_perl” in a gdb backtrace, you’re running threaded perl, otherwise use the unthreaded version of curinfo.
(gdb) bt
#0 0xffffe410 in __kernel_vsyscall ()
#1 0xb7f78751 in accept () from /lib/tls/i686/cmov/libpthread.so.0
#2 0x081502de in Perl_pp_accept (my_perl=0x81c1008) at pp_sys.c:2565
#3 0x080d10b3 in Perl_runops_debug (my_perl=0x81c1008) at dump.c:1452
#4 0x08065c9b in S_run_body (my_perl=0x81c1008, oldscope=1) at perl.c:1995
#5 0×08065703 in perl_run (my_perl=0x81c1008) at perl.c:1919
#6 0x0805febd in main (argc=3, argv=0xbfccac44, env=0xbfccac54)
at perlmain.c:98
Looks like we’re running threaded perl, so define curinfo:
(gdb) define curinfo
Type commands for definition of “curinfo”.
End with a line saying just “end”.
> printf “%d:%s\n”, my_perl->Tcurcop->cop_line, \
my_perl->Tcurcop->cop_file
> end
Then use it:
(gdb) curinfo
196:/usr/local/share/perl/5.8.7/Catalyst/Engine/HTTP.pm
(gdb)
That’s what line was executing and what file you were in. It’s worth mentioning that this was not a buggy application, just an ordinary Catalyst application waiting for a connection. Not too exciting for ordinary perl debugging (much easier to run the process as perl -d), but when you’ve got an infinite loop in the perl interpreter (for example, an infinite loop in a regex), this can help point you in the right direction.
My first CPAN acknowledgement
It’s a small thing, but I’m listed in the acknowledgements for Test::Class, an excellent little xUnit-with-a-decisively-perl-twist module that we use at work. A star is born?


