Amass

Using Perl and Logrotate to update stats and logs

March 26th, 2008 Luke

I recently moved girasquid.com, and all of my other sites, to my own Linux server - which I built myself.

It’s been a learning experience.

One of the things that I’ve been learning about is awstats, which is my stats utility of choice. In order to keep my log files from becoming too large, I’ve also turned on logrotate, so that it runs at 3:30 AM every day.

The only problem with this is that I’m running using virtualhosts - which means that I either need to create awstats configuration files for each specific virtualhost, and I need to create logrotate rules for each virtualhost’s log files.

They’re all in the same location, though. So I thought to myself: “hey! Why not get Perl to handle updating awstats for me? Then I can just write one logrotate rule for all of my virtualhosts!”. And so I did. This is what the logrotate rule looks like:

/home/*/logs/*.log { notifempty daily rotate 7 compress sharedscripts prerotate /usr/share/utils/updatestats.pl endscript postrotate /etc/init.d/apache2 reload endscript }

Which will nicely rotate both the access.log and error.log files for me(I haven’t quite worked out how to do per-virtualhost FTP logging just yet). The code inside /usr/share/utils/updatestats.pl is:

#!/usr/bin/perl -w use strict; opendir(SITES,'/etc/apache2/sites-enabled'); while(defined(my $site = readdir(SITES))) { next if $site =~ /^\.\.?$/; system("/usr/lib/cgi-bin/awstats.pl -update -config=$site"); } closedir(SITES);

As you can see, I basically loop through all of the currently enabled virtualhosts, and pass their names to awstats so that it will update them. This does require that your virtualhosts be named the same thing in either case(for example, the Apache virtualhost for this site is girasquid.com, and the awstats virtualhost is also girasquid.com), but as long as that’s true then it all works beautifully.

Announcing… git-export!

February 12th, 2008 Luke

I’ve been reading a lot about version control lately, and thinking that I should set up some sort of version control for myself.

At the suggestion of a friend from work, I set up Git on my home Linux server. It’s been a week or so now, and I like it.

The problem is, Git doesn’t have my personal killer feature of source control: FTP exports.

One of my main goals in using source control was being able to keep my projects under source control, and easily export different revisions to my production environment - this would happen over FTP, of course.

Upon further examination, it looked like Git couldn’t do this out of the box - it’s ‘export’ functions were limited to just pushing to other Git repositories.

But then a thought struck me: I know Perl. Why didn’t I just build my own tool?

And so I did. You can check out git-export at the git-export Google Code page.

At the moment, all it can do is export the current HEAD revision of the repository you are in, and then transfer it to a folder that you specify - but I’m planning on adding the ability to pass in the name of a specific commit(maybe even tag, later) so that you can export different revisions if need be.

Initially, it doesn’t work over FTP. But if you use curlftpfs to mount an FTP folder as if it were a normal folder and then use git-export, you’ll be able to transfer the files over FTP. I’ll write a tutorial on how exactly to do it soon.

Perl Snippet: Formatting Phone Numbers

November 22nd, 2007 Luke

This is a Perl snippet that will nicely format 10-digit phone numbers, so that they get returned in the form (xxx) xxx.xxxx:

sub formatPhoneNumber { my $number = shift; die "$number is not a valid 10-digit phone number" unless $number =~ /^\(?([1-9]\d{2})\)?[-., ]*?([1-9]\d{2})[-., ]*?(\d{4})$/; my $formatted = "($1) $2.$3"; return $formatted; }

Perl’s Ternary Operator

July 26th, 2007 Luke

I always seem to forget exactly how Perl’s ternary operator works, and I always have trouble finding something on Google that explains how it works. So here’s how Perl’s Ternary Operator works:

my $var = $boolean_condition ? $true_value : $false_value;

Here’s some sample code:

#!/usr/bin/perl -w use strict; my $test = 0; my $ternary = $test?'true':'false'; print $ternary . "\n"; $test = 1; $ternary = $test?'true':'false'; print $ternary . "\n";

Which, when run under my console, returns this:

Luke@Wolverine:~ $ perl test.pl false true Luke@Wolverine:~ $

Grammatically correct object names

March 26th, 2007 Luke

Has anyone other than me noticed the exceedingly bad grammar in some online games? Instead of saying “You have 2 swords” when you have 2 swords, you get a message like “You have 2 sword”. It’s a disturbing thing to have happen to you.

Recently, while working on Militarism(new project - I’ll talk about it later), I realized that that’s what would happen when a user viewed their units. I had the unit names in the units table, but at the moment it was just their singular name, and…they weren’t grammatically unique in terms of how you would transform them to make them plural. I couldn’t just add an ’s’ to the end. That might work for the Legionnaire unit, but what about the Phalanx?

So, I settled on this solution. Here’s the table setup:CREATE TABLE units ( id int not null auto_increment, name text, plural_name text, PRIMARY KEY(id) ); And here’s the Perl code that I used: # we already executed and bound $sth with $unitID and $unitCount my $singleName = $dbh->prepare("SELECT name FROM units WHERE id = ?"); my $pluralName = $dbh->prepare("SELECT plural_name FROM units WHERE id = ?"); while($sth->fetch) { if($unitCount > 1) { $pluralName->execute($unitID); $pluralName->bind_columns(\$unitName); $pluralName->fetch; } else { $singleName->execute($unitID); $singleName->bind_columns(\$unitName); $singleName->fetch; } } Basically, all we have to do is prepare two statements instead of one, and then check how many units of a specific type a user has. If they have more than 1, we’re going to retrieve the units.plural_name attribute. Otherwise, we’ll just retrieve units.name and use that. This makes it so that if a word needs to be transformed in some special way for plurals, it’s possible. Things like pikeman -> pikemen work just great.