Blog | RSS | Photo Gallery | Wish List     Eric's Blob
Did Someone Say Perl? (Updated Thrice!) Posted at 17:18 by Eric

So, in a bold and brash move, someone actually mentioned Perl at the Perl Mongers Meeting last night. In fact, in addition to Patrick talking about Parrot, we actually wrote Perl code as well. It must be a first.

Jeff had an issue where the wonderful admins at his workplace weren't getting the DNS straight on a new DNS server. So, given several hundred names, and a list of the correct IP's, how does one show the admin's which names don't have correct IP's on the new DNS server? Why, you use Perl of course.

The simple, boring, 10 minute answer is this code:

#!/usr/bin/perl

use strict;
use warnings;

use Net::DNS;

my  =  or die "First argument should be the nameserver\n";
my        =  or die "Second argument should be the file\n";

open FH,  or die "Can't open ]\n";

my  = Net::DNS::Resolver->new( nameservers =>  );

while (my  = ) {

    my (, ) = split /,/, ;
    chomp ;
    check_dns(, );

}

sub check_dns {
    my (, ) = @_;

    my  = ->query(, "A");

    if () {
        my () = ->answer;
        if (->address ne ) {
            print " is off! Says , should be \n";
        }
    }
    else {
      warn "Query on  failed: ", ->errorstring, "\n";
    }
}

That takes a nameserver, and file, as arguments. The file has one name / ip per line. It then looks up the hostname at the specified nameserver... and if the IP the nameserver returns is not the same as the IP listen in the file, it displays an error.

The real fun was, how little code can one use to perform this task? Golf, as they say!

Todd used a bunch of shell commands, and had it in some 75 characters. Well, that doesn't really count, that's like being on a different golf course, but saying you finished with fewer strokes ;-)

At the meeting last night, I was able to get it down to 95 characters of pure Perl:

perl -MSocket -nle '($x,$y)=split/,/;$y;$z=inet_ntoa((gethostbyname($x)));print if$z ne$y' h

I've since shortened it to 81 characters by using a different method to perform the DNS lookup:

perl -MSocket -nle '($x,$y)=split/,/;$z=inet_ntoa inet_aton $x;print if$z ne$y' h

And then, 75 characters by dropping the need for $z, and getting rid of some spaces:

perl -MSocket -nle'($x,$y)=split/,/;print if(inet_ntoa inet_aton $x)ne$y' h

Is it possible to not assign variables in the split? I'm not sure, but I think that may be the only avenue left for shortening it more :-)

Update: Okay, we can in fact drop the variable assignment in split, and use the default array, @_. I was originally hoping split set $a and $b the way sort does... it doesn't seem to. But, using @_. we can get it down to 73 characters:

perl -MSocket -nle'split/,/;print if(inet_ntoa inet_aton $_)ne$_' h

Update 2: Aha! We can get rid of split, with a good 'ol regex, bringing us in at 69 characters:

perl -MSocket -nle'/(.*),(.*)/;print if(inet_ntoa inet_aton$1)ne$2' h

Update 3: Woo! Save a char by using -p instead of -n, 68 chars:

perl -MSocket -ple'/(.*),(.*)/;$_=""if(inet_ntoa inet_aton$1)eq$2' h
| |

Post a Comment
    Name:
    URL/Email: [http://... or mailto:you@wherever] (optional)
    Title: (optional)
    Comments:
      Use HTML for formatting. Allowed HTML: <a> <p> <b> <i> <u> <hr> <br> <ol> <ul> <li>

trackback

TrackBack ping me at:

http://www.openthought.org/blosxom.cgi/Blog/Computers/Organizations/HPM/hpm_20060518.trackback