Thursday, 22 March 2007

Mass-migrating websites - DNS changes tracking

First shot - migrate several hundreds of websites from one server to another... Copying is a simple task... creating config files is simple task... changing DNS records is boring (and simple)... but keeping track of which DNS domains were properly propagated and which not is a stupid and annoying job... Perl to the rescue!
This is based on several assumptions:
  • we use apache2-like way of configuration - all virtual hosts in separate files
  • each file has one ServerName statement and possibly ServerAlias with unlimited amount of names following it
  • each file has the same name as domain - either with or without 'www' at the beginning (so for sure it has at least one dot in the name)
  • we are only interested in the DNS records pointing to the right IP

I rolled out a simple perl script that does it for me. As most of the domains I manage have TTL between 20 minutes and 3 hours I run it several times a day and just check the list of domains that were transferred or not...

use strict;

my @files=glob ("*.*");
my %checks;
my $k;
my $expected_IP = '';

foreach my $k (@files) {
  open (FH, $k);
  while(<FH>) {
    if (/Server(Name|Alias)s+(.*?)$/i) {
      $checks{$k} .= "$2 ";

my (%OK, %NOK);

foreach my $k (sort keys %checks) {
  my @t = split(/s+/, $checks{$k});
  print "Testing file $kn";
  foreach my $h (sort @t) {
    next if length($h) < 5;
    my $r = `host -t A $h`;
    if ($r =~ /SERVFAIL/) {
      print "  - $h (domain NOT REGISTERED)n";
    } elsif ($r =~ /NXDOMAIN/) {
      print "  - $h (domain exists but HOST UNKNOWN)n";
    } elsif (length($r) < length($h)) {
      print "  - $h (query returned NO DATA at all)n";
    } else {
      $r =~ m/s+(d{1,3}.d{1,3}.d{1,3}.d{1,3})$/;
      $1 eq $expected_IP ? print "  + $hn" : print "  - $h ($1)n";

As a result I get a list like (domain names are fake of course):

Testing file
  + (
  - (domain exists but HOST UNKNOWN)
Testing file
  - (
  - (

... as a finishing touch - cron it, pipe it to email... | mail -t "DNS domains maps on `date`"

Have fun!