LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-12-2009, 11:08 AM   #1
0.o
Member
 
Registered: May 2004
Location: Raleigh, NC
Distribution: Debian, Solaris, HP-UX, AIX
Posts: 208

Rep: Reputation: 35
Perl: Check for free IPs


I am trying to write a script to parse a hosts file and pull out missing IP addresses. I am unable to get the logic correct.

Code:
#!/usr/bin/perl

use warnings;
use strict;
my %hosts;

open(HOSTS, "</home/terryd/hosts") or die "Can't open file: $@";
&PopHash;
&FreeIPs;

sub FreeIPs
{
        my $key;
        my $num;
        for $key (keys %hosts)
        {
                foreach(1..254)
                {
                        if(!$hosts{10.4.11.$_})
                        {
                                print "10.4.11.$_ is free\n";
                        }
                }
        }
}

sub PopHash
{#Start of function

        foreach(<HOSTS>)
        {
                chomp;
                next if s/#.*//;
                next if s/^\s+$//;

        if(/10.4.11/)
        {
        {

                my ($ip, $host) = split;

                        if(!$hosts{$host})
                        {
                                $hosts{$ip} = $host;
                        }
        }
        }
}#End of function
close(HOSTS);
 
Old 02-12-2009, 12:26 PM   #2
Big_Vern
LQ Newbie
 
Registered: Jan 2008
Posts: 9

Rep: Reputation: 1
Quote:
Originally Posted by 0.o View Post
I am trying to write a script to parse a hosts file and pull out missing IP addresses. I am unable to get the logic correct.

Code:
      if(!$hosts{10.4.11.$_})

I can see a few minor issues with your script but to answer your question, you need to quote the beginning of the IP address as the dots are being treated as concatenation operators.
 
Old 02-12-2009, 12:54 PM   #3
0.o
Member
 
Registered: May 2004
Location: Raleigh, NC
Distribution: Debian, Solaris, HP-UX, AIX
Posts: 208

Original Poster
Rep: Reputation: 35
Yeah, I figured that out right after posting that. I just removed the first three octets and used the fourth as my key value. Since the addresses are /24 that is all I am concerned about.

What other issues do you see?
 
Old 02-12-2009, 01:51 PM   #4
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Code:
if(!$hosts{10.4.11.$_})
- this is really bad style - you create a hash key if it doesn't exist yet.

The correct style is

Code:
unless(exists $hosts${"10.4.11.$_"})
.
 
Old 02-12-2009, 05:58 PM   #5
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,360

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
Code:
&PopHash;
&FreeIPs;
The '&'s are unnecessary/deprecated. They are the old school pre Perl v5 way of calling a sub. Now, in most circumstances it means a ref-to-sub, which is not what you mean here.

Also, in sub PopHash you seem to have a doubled set of {} after the if().

In general, if you are using subs, (which is good) I'd pass the hash to & from the subs, not treat it as a global. In bigger progs this can lead to confusion.

In
Code:
open(HOSTS, "</home/terryd/hosts") or die "Can't open file: $@";
use
Code:
open(HOSTS, "<", "/home/terryd/hosts") or die "Can't open file /home/terryd/hosts: $!";
3-arg open is recommended best practice.
 
Old 02-13-2009, 12:12 PM   #6
Big_Vern
LQ Newbie
 
Registered: Jan 2008
Posts: 9

Rep: Reputation: 1
Quote:
Originally Posted by 0.o View Post
Yeah, I figured that out right after posting that. I just removed the first three octets and used the fourth as my key value. Since the addresses are /24 that is all I am concerned about.

What other issues do you see?
Apart from the few minor things pointed out by the others, I wasn't sure why you were iterating through each element in the hash, then iterating through the numbers 1..254 (or 1..255?). Does this not mean you're checking if an IP exists in the hash, multiple times (depending on the size of the hash)?
 
Old 02-13-2009, 12:20 PM   #7
0.o
Member
 
Registered: May 2004
Location: Raleigh, NC
Distribution: Debian, Solaris, HP-UX, AIX
Posts: 208

Original Poster
Rep: Reputation: 35
I changed the script to this:

Code:
#!/usr/bin/perl                                                               
                
use warnings;                                                                 
use strict;                                                                   
my %hosts;                                                                    

open(HOSTS,"<", "/etc/hosts") or die "Can't open file: $@";
&PopHash;                                                  
&FreeIPs;                                                  

sub FreeIPs
{
        foreach(1..254)
        {
                unless(exists $hosts{$_})
                {
                                print "10.4.11.$_ is free\n";

                }
        }
}

sub PopHash
{

        foreach(<HOSTS>)
        {
                chomp;
                next if s/#.*//;
                next if s/^\s+$//;

        if(/10.4.11/)
        {
                my ($ip, $host) = split;
                my($junk1,$junk2,$junk3,$data) = split /\./, $ip;

                unless(exists $hosts{$data})
                {
                        $hosts{$data} = $host;
                }
        }
        }
}
close(HOSTS);
exit(0);
I have changed most things that were mentioned. However, with the use of strict, I am unable to change the way I call the subs. Also, the reason I was iterating through the numbers 1..254 was to check for the existance of that IP. The range of IPs I am checking is a /24 (10.4.11.1-254).

Last edited by 0.o; 02-13-2009 at 12:29 PM.
 
Old 02-13-2009, 12:38 PM   #8
Telemachos
Member
 
Registered: May 2007
Distribution: Debian
Posts: 754

Rep: Reputation: 60
Quote:
Originally Posted by 0.o View Post
However, with the use of strict, I am unable to change the way I call the subs.
Yes, you can actually:
Code:
FreeIPs();
PopHash();
I would also put the open call inside the subroutine where it runs, and use a scalar file-handle:
Code:
open my $file_handle, '<', '/etc/hosts' or die "Can't open '/etc/hosts' for reading: $!";
Then replace <HOSTS> with <$file_handle>. You can do this as of Perl 5.6, and it's better than bareword filehandles in lots of ways (local to a block, easier to pass around, etc.). http://perldoc.perl.org/perlopentut....ct-Filehandles

Now that I look, you also don't want to substitute in your regular expressions in PopHash - you only want to match. If you're skipping the item anyhow, why perform any substitution? (You're never going to process that line, and you're not writing the file back out after editing it. So why bother?):
Code:
next if m/^#/;      # Skip lines that are only comments
next if m/^\s+$/;   # Skip lines that are blank
You might also use a slice rather than assign three dummy values in that same subroutine:
Code:
my $data = (split /\./, $ip)[3];

Last edited by Telemachos; 02-13-2009 at 12:55 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Getting things straight: Apache, SSL, Multiple External IPs / Internal IPs robin.com.au Linux - Server 21 10-13-2007 11:39 PM
Unicode Character Check in Perl gjagadish Programming 2 08-21-2007 11:31 PM
Perl Script To Check Logs Crashed_Again Programming 0 11-13-2004 03:13 PM
how to define a specific range of IPs and/or multiple IPs in an iptables rule?... TheHellsMaster Linux - Security 9 09-20-2004 10:06 AM
Please check this program(perl) for me! Rex_chaos Programming 2 04-25-2002 06:56 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:56 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration