IRC Client - channel latitude and longitude details - irc

Is there a way to retrieve latitude and longitude details of IRC channel so that I can locate the same on Map.
Thanks.

To get the locations of the people in the channel, you could simply look at their hostname - names on IRC are made up of a nickname, a username, and a hostname in the format nickname!username#hostname.
The hostname could be one of three things - an IP address, a DNS name, or a "cloak". You could use a DNS client to convert the hostname into an IP address, and then with the IP addresses you could use an IP geolocation tool (such as ipinfodb.com which has a nice free API), and retrieve the latitude and longtitude of each user.
If the hostname is a cloak, and the format of this varies between networks, then there's no way (unless you have advanced privileges on the IRC network) to get the real IP/hostname (and hence location) of that user.

Radoslaw Zielinski (radek at pld-linux dot org) wrote a Perl script for geolocation of nicknames in the XChat IRC client:
I wrote a simple plugin to look up the IP address in the Maxmind GeoIP lookup database, you can find it here: xchat-geo.pl. See “perldoc xchat-geo.pl” for the installation instructions.
Usage:
/geo some_nickname
Output:
[17:33] ==> some_nickname | US San Francisco CA 37.7525 -122.3194 n=somenick#some.host
Original blog post: www.radek.cc/2009/09/06/irc-xchat-geolocation-plugin/
It requires that you install:
Perl
one of the Maxmind GeoIP databases (some are free)
the Maxmind Geo::IP module (its API for Perl)
XChat with a Perl scripting interface plugin
xchat-geo.pl, retrieved 2012-03-06:
#!/usr/bin/perl -w
use strict;
use Geo::IP ();
our $VERSION = '0.04';
=head1 NAME
xchat-geo.pl - geolocation plugin for xchat
=head1 SYNOPSIS
perl -MCPAN -e 'install Geo::IP'
chmod +x xchat-geo.pl
mv xchat-geo.pl ~/.xchat/
# in xchat
/unload .xchat/xchat-geo.pl
/load .xchat/xchat-geo.pl
/geo some-nickname
=head1 DESCRIPTION
Usage:
/geo some_nickname
[17:33] ==> some_nickname | US San Francisco CA 37.7525 -122.3194
n=somenick#some.host
Provides a single C</geo> command, which attempts to lookup the IP address in
the maxmind GeoIP database.
Requires the Geo::IP module to be installed, along with the GeoIP City (or its
free GeoLite counterpart); see L<http://www.maxmind.com/app/ip-location> and
L<http://www.maxmind.com/app/geolitecity>.
On my machine, the installed databases look like this:
$ ls -l /usr/share/GeoIP
lrwxrwxrwx 1 root root 15 Sep 6 16:54 GeoIPCity.dat -> GeoLiteCity.dat
-rw-r--r-- 1 root root 877738 Sep 6 16:25 GeoIP.dat
-rw-r--r-- 1 root root 27711885 Sep 6 16:31 GeoLiteCity.dat
Released 2009-09-06
=head1 AUTHOR
Radoslaw Zielinski E<lt>radek#pld-linux.orgE<gt>
http://radek.cc/2009/09/06/irc-xchat-geolocation-plugin/
=head1 LICENSE
GPL v3
=cut
our $geo = Geo::IP->open_type( Geo::IP::GEOIP_CITY_EDITION_REV1 ) # Geo::IP::GEOIP_STANDARD
or die "can't load the GeoIP database";
Xchat::print('xchat geo starting');
Xchat::register( 'xchat geo', $VERSION, 'geo location for xchat', \&unload );
Xchat::hook_print( 'Join', \&Join, );
Xchat::hook_command( 'geo', sub { geo(#_); Xchat::EAT_ALL; }, );
# for debugging / plugin development
#Xchat::hook_command( 'xev', sub { eval $_[1][0]; Xchat::EAT_ALL; }, );
sub Join {
my ( $user, $channel, $host ) = #{ $_[0] };
my $r = record_from_ihost($host);
Xchat::printf( "-\x0311->\x03\t\x02%s \x0f\x0314(\x0311%s\x0314) \x03has joined %s [\x0308%s\x0f]",
$user, $host, $channel,
$r && ref $r
? join( ', ', map { defined $_ ? $_ : '' } $r->country_code, $r->city, $r->region, $r->postal_code, )
: '' );
return Xchat::EAT_XCHAT;
}
# /geo some_nickname
sub geo {
my ($cmd) = #_;
defined $cmd->[1] && length $cmd->[1]
or return Xchat::print('nick?');
my $user = Xchat::user_info( $cmd->[1] )
or return Xchat::print("no such nick $cmd->[1]");
my $r = record_from_ihost( $user->{host} )
or return;
return ref $r
? Xchat::print(
' ==> ' . join "\t", $user->{nick}, $r->country_code, $r->city, $r->region,
$r->latitude, $r->longitude, $r->postal_code, $user->{host}
)
: Xchat::print($r);
}
# input: nick and hostname, as reported by xchat
# - n=user#hostname
# - n=user#IP.address
# - n=user#some/freenode/cloak (useless)
# output: a string with error message or a Geo::IP record
sub record_from_ihost {
my $ihost = shift
or return;
( my $nick = $ihost ) =~ s/^.=|\#.*//g;
$ihost =~ /^ [^#]* \# (?: ((?:\d{1,3}\.){3}\.\d{1,3}) | ([a-zA-Z\d_-]+\.[.a-zA-Z\d_-]+) ) (?: \s.* )? $/x
or return "no useful host for <$nick> -- $ihost";
my $r = ( $1 ? $geo->record_by_ip($1) : $geo->record_by_name($2) )
or return "no useful geo info for <$nick> -- $ihost " . ( $1 ? "1: $1" : "2: $2" );
return $r;
}
sub unload {
undef $geo;
Xchat::print('xchat geo exiting');
}
# vim: ts=4 sw=4 noet

Related

Why am I getting warnings about an uninitialized value in this Perl program? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I get these errors
Use of uninitialized value $vm_name in pattern match (m//) at testscript.pl line 164, <STDIN> line 1.
Use of uninitialized value $vm_name in concatenation (.) or string at testscript.pl line 173, <STDIN> line 1.
Can anyone help? I have a feeling it is to do with the subroutine but cannot figure it out exactly. I am new to Perl and have been poring over this for hours.
# !/usr/bin/perl
use strict;
use warnings;
use feature ":5.10";
###############################################################################
# Static Variables
my $templateID = "XXXXXXXXXX";
my $serviceID = "XXXXXXXXXXX";
###############################################################################
###############################################################################
# Global Variables
my $zone;
my $input;
my $zone_ID;
my $vm_name;
my $net_default;
my $net_secondary;
my $vm_ID;
my $start;
my $char_count;
my $ipaddr_1;
my $ipaddr_2;
###############################################################################
# ----------------------- BASIC CONFIGURATIONS [ZONES] ------------------------
print " *** ";
print "
ZONES: paris, milan, berlin, geneva, amsterdam, london, slough";
print " which zone would you like to deploy to? \n ";
# Capture input for ZONE
$input = <STDIN>;
# Data formatting
$input =~ s/^\s+|\s+$|^\t//g;
$zone = lc $input;
# Declare ZONE to USER
print "You are deploying to $zone \n";
# Map input to function
# ZONE PARIS
if ($zone eq "paris") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "374b937d-2051-4440-b02c-a314dd9cb27e";
}
# ZONE MILAN
elsif ($zone eq "milan") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "58848a37-db49-4518-946a-88911db0ee2b";
}
# ZONE BERLIN
elsif ($zone eq "berlin") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "fc129b38-d490-4cd9-acf8-838cf7eb168d";
}
# ZONE GENEVE
elsif ($zone eq "geneva") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "1ef96ec0-9e51-4502-9a81-045bc37ecc0a";
}
# ZONE AMSTERDAM
elsif ($zone eq "amsterdam") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "3c43b32b-fadf-4629-b8e9-61fb7a5b9bb8";
}
# ZONE SLOUGH
elsif ($zone eq "slough") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "5343ddc2-919f-4d1b-a8e6-59f91d901f8e";
}
# ZONE LONDON
elsif ($zone eq "london") {
print "Deploying to $zone\n";
# assign zone id
$zone_ID = "f6b0d029-8e53-413b-99f3-e0a2a543ee1d";
}
# ELSE
else {
print "Please choose a ZONE";
system('./deploy_vm');
}
# SUBROUTINE: Assigning Virtual Machine name
sub vm_name {
# Name of Virtual Machine
print "Enter name of Virtual Machine: \n";
print "[VDC Bug: Please do not include '_' in the name]\n";
my $vm_name = <STDIN>;
# Data formatting
$vm_name =~ s/^\s+|\s+$//g;
print("VM Name: $vm_name");
}
# Apply input filters (no underscores, length constraints)
if (my $vm_name =~ /_/) {
return ('underscore error');
print "Cannot use underscore in VM name, please try again";
vm_name();
}
# DisPlay config
print "
$vm_name will be provisioned with:
1GB HDD and compute offering of 2CPUs with 2GB-RAM";
# ----------------------- NETWORK CONFIGURATIONS ------------------------------
# Gather network information
print "available networks in $zone";
system('cloudmonkey list networks zoneid=$zone_id filter=name,id');
# Users to choose Networks through display
print "";
# Default NIC & IP address
print "please enter Network ID for Default NIC:\n";
$net_default = <STDIN>;
# IP Address DEFAULT
print "please enter IP address\n";
$ipaddr_1 = <STDIN>;
# formatting IP address
$ipaddr_1 =~ m/^\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
# SECONDARY NIC & IP address
print "please enter Network ID for secondary NIC";
$net_secondary = <STDIN>;
# IP Address SECONDARY
print "please enter IP address\n";
$ipaddr_2 = <STDIN>;
# Formatting IP address
$ipaddr_2 =~ m/^\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
print "IP ADDRESS is $ipaddr_2\n";
# Deployment notice
print "... deploying ... \n";
# Provision Machine
# + startvm=false due to provisioning constraints
system('cloudmonkey deploy virtualmachine startvm=false name=$vm_name diplayname=$vm_name zoneid=$zone_id templateid=$templateID serviceofferingid=$serviceID networkids=$net_default ipaddress=$ipaddr_1');
# Add second network to VM
print "Adding second network to VM";
system('cloudmonkey addNicToVirtualMachine networkid=$network_id_second ipaddress=$ip_address_second virtualmachineid=$vm_id');
# Display machine ID
print "$vm_ID";
my $feedback = system('cloudmonkey list networks zoneid=$zone_id filter=name,id');
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
# # Sotiris Comments # #
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
# if (lc($feedback) =~ /error/) {
# Warn user and fall back to known state. }
# User to copy&paste ID
print "Paste VM ID:\n";
$vm_ID = <STDIN>;
# Data Validation
$vm_ID =~ s/^\s+|\s+$//g;
$vm_ID = lc $vm_ID;
$char_count = length($vm_ID);
# IF statement to impliment length validation
if ($char_count != 36) {
print "your ID is too long/short";
}
# Start Virtual Machine?
print "Start Virtual Machine $vm_name?";
$start = <STDIN>;
if ($start eq "yes") {
system('');
}
elsif ($start eq "no") {
system('');
}
# done!
You have posted a poor piece of Perl code that you have presumably written all in one chunk. Programming doesn't work like that, especially in script-like languages, and you should write just two or three lines at a time before testing that it works as you expect. That way, if you have a question at all, it can be about just a few lines of code whose input you know but whose behaviour you can't explain. In this case your Use of uninitialized value errors are the least of your worries.
You really shouldn't delcare everything at the top of your program, C-style. Declarations should be as close as possible to their first point of use.
Comments should be kept to the absolute minimum. It is very rare that a program contains a construct that is incomprehensible without the addition of comments, and your program is inflated around 100% by unnecessary commenting
The mapping between zones and zone IDs is best implemented as a Perl hash, not as an if/elsif/else chain
The vm_name subroutine is never called except in the test if (my $vm_name =~ /_/) { ... }, and your use of my here declares a new $vm_name which will always be undef
The lines you have commented with formatting IP address do no formatting at all. They test whether the variables' contents match the regular expression, and then ignore and discard the result of the test
The calls to system use single quotes, so the string is passed verbatim to the cloudmonkey program, and no interpolations are done. For instance, the variable names $vm_name, $zone_id, $templateID, $serviceID etc. are not replaced by their values
There are several more problems, but I strongly suggest that, as I said at the start, you should write the program incrementally in very small parts. That way you have the encouraging pleasure of seeing your code in action and wortking, as well as knowing for sure that, as you write, you have a firm foundation to build on.
if (my $vm_name =~ /_/)
will always warn Use of uninitialized value $vm_name in pattern match under warnings, as you're mistakenly declaring another lexical with my inside if condition.
Also you should sanitize user input as
my $vm_name = <STDIN>;
returned undefined if the user presses Ctrl-D or there was end of piped input.
You're reached the end of the input, but you pretend you actually read something in. Maybe you want to add
die "Premature EOF\n" if !defined($vm_name);
after
my $vm_name=<STDIN>;

awk sed perl to merge rows based on keyword match

I've been banging my head head against the wall on this issue due to my limited awk/sed wizardry. I'm happy to use awk,sed,bash,perl, or whatever to accomplish this text manipulation.
I have the following output and would like to merge lines based on a sort of key match:
Node: server1
Active Server: SECONDARY
Standby Server: PRIMARY
Primary 192.168.1.1
Secondary 192.168.1.2
Node: server2
Active Server: PRIMARY
Standby Server: SECONDARY
Primary 10.1.1.1
Secondary 10.1.1.2
Desired output:
Node: server1
Active Server: Secondary 192.168.1.2
Standby Server: Primary 192.168.1.1
Node: server2
Active Server: Primary 10.1.1.1
Standby Server: Secondary 10.1.1.2
So I need the lines to merge based on the words "primary" and "secondary". My first thought was to change "Primary" to "PRIMARY" so it would be easier to match.
My eventual goal is to have this:
server1,Active,192.168.1.2,Standby,192.168.1.1
server2,Active,10.1.1.1,Standy,10.1.1.2
(but I can figure this part out after help merging the rows)
Thanks for the help!
This Perl solution seems to do what you ask. It simply pulls the values into a hash line by line, and dumps the hash contents when all the required values are present.
Update I've used any from List::Util in place of grep to make the code more legible.
use strict;
use warnings;
use autodie;
use List::Util 'any';
my #names = qw/ node active standby primary secondary /;
open my $fh, '<', 'myfile.txt';
my %server;
while (my $line = <$fh>) {
next unless my ($key, $val) = lc($line) =~ /(\w+).*\s+(\S+)/;
%server = () if $key eq 'server';
$server{$key} = $val;
unless ( any { not exists $server{$_} } #names ) {
printf "%s,Active,%s,Standby,%s\n", #server{'node', $server{active}, $server{standby}};
%server = ();
}
}
output
server1,Active,192.168.1.2,Standby,192.168.1.1
server2,Active,10.1.1.1,Standby,10.1.1.2
It is dense and very ugly multi-liner,
perl -00 -nE'
s/ ^(\w+)\s+([\d.]+)\s* / $s{$1}=$2; ""/xmge;
($l=$_) =~ s! \s*\w+:\s*|\n !,!xg;
$l =~ s|\U$_|$s{$_}| for keys %s;
($_=$l) =~ s/^,|,$//g;
say
' file
output
server1,Active,192.168.1.2,Standby,192.168.1.1
server2,Active,10.1.1.1,Standby,10.1.1.2
Explanation
# -00 => instead of single line read lines into $_ until \n\n+
perl -00 -nE'
# read and remove 'Primary|Secondary IP' into $s{Primary} = IP
s/ ^(\w+)\s+([\d.]+)\s* / $s{$1}=$2; ""/xmge;
# replace 'something:' or new line by ','
($l=$_) =~ s! \s*\w+:\s*|\n !,!xg;
# replace SECONDARY|PRIMARY with actual IP address
$l =~ s|\U$_|$s{$_}| for keys %s;
# remove ',' at beginning and end of the string
($_=$l) =~ s/^,|,$//g;
# print result
say
' file
You can use tr to eliminate spaces, then sed to put then back in the right place and use perl to get the output you want:
Input file:
tiago#dell:/tmp$ cat file
Node: server1
Active Server: SECONDARY
Standby Server: PRIMARY
Primary 192.168.1.1
Secondary 192.168.1.2
Node: server2
Active Server: PRIMARY
Standby Server: SECONDARY
Primary 10.1.1.1
Secondary 10.1.1.2
Script:
tiago#dell:/tmp$ cat test.sh
#! /bin/bash
tr -d '\n' < $1 | sed -r 's/(Node:)/\n\1/g' |\
perl -lne '
/^\s+$/ && next;
/Node:\s+(\w+.*?)\s/ && {$server=$1};
/Active Server:\s+(\w+.*?)\s/ && {$active=$1};
/Standby Server:\s+(\w+.*?)\s/ && {$standby=$1};
/Primary\s+(\w+.*?)\s/ && {$pri=$1};
/Secondary\s+(\w+.*?)\s/ && {$sec=$1};
if ( "$active" eq "PRIMARY" ){
$out="$server,Active,$pri,Standby,$sec";
}else{
$out="$server,Active,$sec,Standby,$pri";
}
print $out;
'
Execution:
tiago#dell:/tmp$ bash test.sh file
server1,Active,192.168.1.2,Standby,192.168.1.1
server2,Active,10.1.1.1,Standby,192.168.1.2
Or using a one-liner for the intermediate desired solution (final solution to follow):
perl -00 -lpe '
s/ Server: \K(\w+)(?=.*^(\1[^\n]*))/$2/ismg;
s/\n[^:]+$//;
' file.txt
Outputs:
Node: server1
Active Server: Secondary 192.168.1.2
Standby Server: Primary 192.168.1.1
Node: server2
Active Server: Primary 10.1.1.1
Standby Server: Secondary 10.1.1.2
Explanation:
Switches:
-00: process input in paragraph mode (separated by double returns)
-l: enable line ending processing
-p: assume "while (<>) { ...; print; }" loop around program
-e: evaluate perl code
Code:
Replace all Server values with a matching line that begins with the same key
Remove the server list at the bottom.
To get the final solution you want, the following one liner will accomplish that goal.
There are some slight changes from the first solution like using -n instead of -p because we want to move from two newlines between records to one new line. However, the regex tools are the same:
perl -00 -ne'
s/ Server: (\w+)(?=.*^\1\s+(\S+))/:$2/ismg;
s/\n[^:]+$//;
s/^Node: //;
s/[\n:]/,/g;
print "$_\n";
' file.txt
Outputs:
server1,Active,192.168.1.2,Standby,192.168.1.1
server2,Active,10.1.1.1,Standby,10.1.1.2
awk '
$1 == "Active" {active = tolower($NF); next}
$1 == "Standby" {standby = tolower($NF); next}
$1 == "Primary" {ip["primary"] = $0; next}
$1 == "Secondary" {
ip["secondary"] = $0
print "Active Server:",ip[active]
print "Standby Server:",ip[standby]
next
}
1
'
This assumes the "Secondary" line is at the end of a "block".
To achieve your next output:
awk -v OFS="," '
$1 == "Node:" {node = $NF}
$1 == "Active" {active = tolower($NF)}
$1 == "Standby" {standby = tolower($NF)}
$1 == "Primary" {ip["primary"] = $2}
$1 == "Secondary" {
ip["secondary"] = $2;
print node, "Active",ip[active],"Standup",ip[standby]
}
'
Responding to jhill's comment:
awk -v RS="" -v OFS=, '{
node = active = standby = ""
delete ip
for (i=1; i<NF; i++) {
if ($i == "Node:") {node=$(++i)}
else if ($i == "Active") {active = tolower( $(i+=2) )}
else if ($i == "Standby") {standby = tolower( $(i+=2) )}
else if ($i == "Primary") {ip["primary"] = $(++i)}
else if ($i == "Secondary") {ip["secondary"] = $(++i)}
}
print node, "Active", ip[active], "Standup", ip[standby]
}'
A bit more verbose:
use strict;
use warnings;
use feature qw/say/;
my $struct;
local $/ = 'Node: ';
for my $record (<DATA>) {
next if $record =~ /^Node:/; # skip first
my ($node, #values) = split /\n\s*/, $record;
for my $line (#values) {
my ($intent, $actual, $ip);
if ( ($intent, $actual) = $line =~ /(Active|Standby) Server: (.*)$/ ) {
$struct->{$node}{lc($intent)} = lc($actual);
}
elsif ( ($actual, $ip) = $line =~ /(Primary|Secondary) (.*)$/ ) {
$struct->{$node}{lc($actual)} = $ip;
}
}
}
for my $node (sort keys %$struct) {
printf "Node: %s\n", $node;
printf "Active server: %s %s\n", ucfirst $struct->{$node}{active}, $struct->{$node}{$struct->{$node}{active}};
printf "Standby server: %s %s\n", ucfirst $struct->{$node}{standby}, $struct->{$node}{$struct->{$node}{standby}};
print "\n";
}
## Desired final output is simpler:
for my $node (sort keys %$struct) {
say join ',', $node, 'Active', $struct->{$node}{$struct->{$node}{active}}, 'Standby', $struct->{$node}{$struct->{$node}{standby}};
}
__DATA__
Node: server1
Active Server: SECONDARY
Standby Server: PRIMARY
Primary 192.168.1.1
Secondary 192.168.1.2
Node: server2
Active Server: PRIMARY
Standby Server: SECONDARY
Primary 10.1.1.1
Secondary 10.1.1.2
Here's an option in awk.
#!/usr/bin/awk -f
# Output processing goes in a function, as it's called from different places
function spew() {
split(servers[d["active"]], active);
split(servers[d["standby"]], standby);
printf("%s,%s,%s,%s,%s\n",
d["name"], active[1], active[2], standby[1], standby[2]);
}
# trim unnecessary (leading) whitespace
1 { $1=$1; }
# Store our references
$1=="Active" {
d["active"]=tolower($3);
}
#
$1=="Standby" {
d["standby"]=tolower($3);
}
# And store our data
/^ *[A-za-z]+ [0-9.]+$/ {
servers[tolower($1)]=tolower($0);
}
# Then, if we hit a new record, process the last one.
$1=="Node:" && length(d["name"]) {
spew();
}
# And if we've just process a record, clear our workspace.
$1=="Node:" {
delete d;
delete s;
d["name"]=$2;
}
# Finally, process the last record.
END {
spew();
}
An advantage of this over some of the other solutions is that it can handle names other than "primary" and "secondary". The idea is that if you have data like:
Node: serverN
Active Server: starfleet
Standby Server: babylon5
starfleet 172.16.0.1
babylon5 172.16.0.2
the Active/Standby lines will refer to a record by its index, rather than assuming "Primary" or "Secondary".
I've normalized everything to lower case for easier handling, but you can of course adjust tolower() to suit.
awk ' s==0{print;s=1;next;}
s==1{i=$0;s=2;next;}
s==2{j=$0;s=3;next;}
s==3{r1=$0;s=4;next;}
s==4{r2=$0;
sub(/SECONDARY/,r2,i);sub(/PRIMARY/,r1,j);
sub(/SECONDARY/,r2,j);sub(/PRIMARY/,r1,i);
s=5; print i;print j;next}
s==5{s=0;print}' input.txt
Output:
Node: server1
Active Server: Secondary 192.168.1.2
Standby Server: Primary 192.168.1.1
Node: server2
Active Server: Primary 10.1.1.1
Standby Server: Secondary 10.1.1.2
Prints first line of the current input section, stores next four lines in variables, then makes replacements and then print the result. then reads and print the blank line and starts again for next section.
You can use this awk
awk -v RS="" '{$5=tolower($5);sub(".",substr(toupper($5),1,1),$5);$8=tolower($8);sub(".",substr(toupper($8),1,1),$8);print $1,$2"\n"$3,$4,$5,$10"\n",$6,$7,$8,$12}' file
Node: server1
Active Server: Secondary 192.168.1.1
Standby Server: Primary 192.168.1.2
Node: server2
Active Server: Primary 10.1.1.1
Standby Server: Secondary 10.1.1.2
By sette setting RS to nothing, awk works with group of line.

how do I check if a domain name is available (in bulk)?

I am looking to do a bulk domain name lookup to see if some domain names are available for purchase. I couldn't find a perl module, but it seems like there should be a way to do this in perl. I am looking for something free. thx!
From here: http://www.webhostingtalk.com/showthread.php?t=625723
Here’s a quick perl script that requires Net :: DNS (fairly common module).
#!/usr/bin/perl
# Domains Available
# Josh Skidmore <josh#vorcado.com>
# 05 August 2007 | 11:40p EST
# Requirements
use Net::DNS;
# Variables
%VAR = (
db => './domains.txt',
);
# Open file
open (DB,$VAR{'db'});
my (#domains) = <DB>;
close (DB);
# Test domains
foreach my $domain (#domains)
{
chomp($domain);
my ($available) = &check_domain(domain => $domain);
if ($available)
{
print "$domain is available.<br />\n";
}
else
{
print "$domain is NOT available<br />\n";
}
}
sub check_domain {
# Test domain for existance
# Josh Skidmore <josh#vorcado.com>
# 05 August 2007 | 11:42p EST
# Variables
my (%DATA) = #_ ;
my ($available) = 0;
# Start Net::DNS
my $res = Net::DNS::Resolver->new;
$res->udp_timeout(2);
$res->tcp_timeout(2);
my ($domain) = $res->search($DATA{'domain'});
if ($domain)
{
($available) = 1;
}
# Output
return ($available);
}
There are plenty of whois-like modules on CPAN. Net::Whois::Parser looks promising, for one.
Barring that, the whois command is available in Linux and other Unix-y systems (including Cygwin for windows). There's also a whois script in Perl on CPAN. Running those programs is the easy part. The tricky part, which Perl can definitely help with, is parsing the output from those programs.

How do I create valid IP ranges given an IP address and Subnet mask in Perl?

How do I create valid IP ranges given an IP address and Subnet mask in Perl? I understand the concept of generating the IP ranges but need help writing in Perl. For example, if I AND the IP address and subnet mask I get the subnet number. Adding 1 to this number should give me the first valid IP. If I invert the subnet mask and OR with the subnet number, I should get the broadcast address. Subtracting 1 from it should give the last valid IP address.
See perldoc perlop for information about the bitwise operators (they are the same as in most other C-like languages):
& is bitwise AND
| is bitwise OR
^ is bitwise XOR
>> is right-shift
<< is left-shift
However, if you really want to do some work with network blocks and IP addresses (as opposed to simply answering a homework assignment - although I'm curious what course you'd be taking that used Perl), you can avoid reinventing the wheel by turning to CPAN:
Net::Netmask
Network::IPv4Addr
If you want to play with bitwise operators yourself, it becomes this:
#!/usr/bin/perl
use strict;
use warnings;
use Socket;
my $ip_address = '192.168.0.15';
my $netmask = 28;
my $ip_address_binary = inet_aton( $ip_address );
my $netmask_binary = ~pack("N", (2**(32-$netmask))-1);
my $network_address = inet_ntoa( $ip_address_binary & $netmask_binary );
my $first_valid = inet_ntoa( pack( 'N', unpack('N', $ip_address_binary & $netmask_binary ) + 1 ));
my $last_valid = inet_ntoa( pack( 'N', unpack('N', $ip_address_binary | ~$netmask_binary ) - 1 ));
my $broadcast_address = inet_ntoa( $ip_address_binary | ~$netmask_binary );
print $network_address, "\n";
print $first_valid, "\n";
print $last_valid, "\n";
print $broadcast_address, "\n";
exit;
With Net::Netmask it's easier to understand:
#!/usr/bin/perl
use strict;
use warnings;
use Net::Netmask;
my $ip_address = '192.168.0.15';
my $netmask = 28;
my $block = Net::Netmask->new( "$ip_address/$netmask" );
my $network_address = $block->base();
my $first_valid = $block->nth(1);
my $last_valid = $block->nth( $block->size - 2 );
my $broadcast_address = $block->broadcast();
print $network_address, "\n";
print $first_valid, "\n";
print $last_valid, "\n";
print $broadcast_address, "\n";
exit;
Quick & dirty way to find the subnet mask:
use Socket;
my $subnet_mask = inet_ntoa(inet_aton($ip_str) & inet_aton($mask_str)):
Following Snippet can help you to find ip address and subnet mask on rhel7
my $ip=`hostname -i`;
my $subnet = `ip addr show|grep -i ".*${ip}/.*"|tail -1|cut -d "/" -f2|cut -d " " -f1`;

Reverse DNS lookup in perl

How do I perform a reverse DNS lookup, that is how do I resolve an IP address to its DNS hostname in Perl?
If you need more detailed DNS info use the Net::DNS module, here is an example:
use Net::DNS;
my $res = Net::DNS::Resolver->new;
# create the reverse lookup DNS name (note that the octets in the IP address need to be reversed).
my $IP = "209.85.173.103";
my $target_IP = join('.', reverse split(/\./, $IP)).".in-addr.arpa";
my $query = $res->query("$target_IP", "PTR");
if ($query) {
foreach my $rr ($query->answer) {
next unless $rr->type eq "PTR";
print $rr->rdatastr, "\n";
}
} else {
warn "query failed: ", $res->errorstring, "\n";
}
Original Source EliteHackers.info, more details there as well.
gethostbyaddr and similar calls. See http://perldoc.perl.org/functions/gethostbyaddr.html
use Socket;
$iaddr = inet_aton("127.0.0.1"); # or whatever address
$name = gethostbyaddr($iaddr, AF_INET);
perl -MSocket -E 'say scalar gethostbyaddr(inet_aton("69.89.27.250"), AF_INET)'
Returns: Can't find string terminator "'" anywhere before EOF at -e line 1.
perl -MSocket -E "say scalar gethostbyaddr(inet_aton(\"69.89.27.250\"), AF_INET)"
Returns: box250.bluehost.com
I have to change the line to use double quotes and then escape out the quotes around the IP address
one-liner:
perl -MSocket -E 'say scalar gethostbyaddr(inet_aton("79.81.152.79"), AF_INET)'
There may be an easier way, but for IPv4, if you can perform ordinary DNS lookups, you can always construct the reverse query yourself. For the IPv4 address A.B.C.D, look up any PTR records at D.C.B.A.in-addr.arpa. For IPv6, you take the 128 hex nibbles and flip them around and append ipv6.arpa. and do the same thing.
If gethostbyaddr doesn't fit your needs, Net::DNS is more flexible.
This might be useful...
$ip = "XXX.XXX.XXX.XXX" # IPV4 address.
my #numbers = split (/\./, $ip);
if (scalar(#numbers) != 4)
{
print "$ip is not a valid IP address.\n";
next;
}
my $ip_addr = pack("C4", #numbers);
# First element of the array returned by gethostbyaddr is host name.
my ($name) = (gethostbyaddr($ip_addr, 2))[0];