IP Check Script
Since I’m cheap and don’t want to pay for a static IP at home, my dynamic IP changes once in a while. I have dynamic DNS set up on my router, but it occasionally (usually after a power outage) messes up and reports an internal IP (192.168.x.x) and kills DNS. So, I came up with a little perl script to check my IP occasionally (out of cron) and email me if there’s a change. Or, email me if it’s been a week and there’s been no change (sanity check to know it’s working). Or, email me if it can’t reach www.whatismyip.com and get a valid IP address (this was failing on me about once a week before I added the retry loop).
Of course, the email bit is dependent on whether or not you have sendmail or postfix (or another) set up correctly.
I’m still learning Perl, so I have no doubt there are things in the script that will make some programmers cringe - all I can say is I’m sorry and I welcome your feedback. I think I put enough comments in the script to make it self-explanatory.
Cron entry0 */8 * * * /tools/ip_check.pl >> /tools/ip_check.log 2>&1
Script
Download the script here.
#!/usr/bin/perl
#A script to check the current public IP and notify someone via email of any changes
#This script will create/use a file for tracking the last known/checked IP address
#The script uses the automation IP check site provided by www.whatismyip.com:
#http://whatismyip.com/automation.asp
use strict;
use LWP::Simple;
use File::stat;
use Env qw(HOME);
#Print a timestamp
print "\n\n\n\nSTARTING the IP Check at " . localtime(time) . "\n";
#Variables
my $file = "/$HOME/current_ip"; #location of the file to check the IP against and store an updated IP
my $url = "http://www.whatismyip.com/automation/n09230945.asp"; #the address to hit for IP query
my $from_addy = "user_from\@domain.com"; #the FROM email address
my $to_addy = "user_to\@domain.com"; #the TO email address
my $counter = 0; #the retry counter starts with this number and increments by 1 right away
my $snooze = 60; #how many seconds to wait before trying to hit the IP URL again
my $trys = 5; #how many times to retry the IP URL
#Get the last known IP from a file - if the file does not exist, the script will make it later
open LOG, "<$file";
my $logged_ip = ;
close LOG;
#Go check the current public IP and try a few times every X seconds if you don't get a response form the URL
my $output = get $url;
if (($output eq "") and ($counter <= $trys)) {
while (($output eq "") and ($counter <= $trys)) {
print "URL output is: $output\n";
print "No response from $url so sleeping for $snooze seconds before checking again.\n";
sleep $snooze;
$counter += 1;
if (($output eq "") and ($counter == $trys)) {
print "The check has returned no result after trying $counter time(s) every $snooze seconds - sending an email and dying.\n";
open (MAIL, "|/usr/sbin/sendmail -t ");
print MAIL "From: $from_addy\n";
print MAIL "To: $to_addy\n";
print MAIL "Content-Type: text/plain\n";
print MAIL "Subject: IP Address Check Failed\n\n";
print MAIL "I have tried to check the IP $counter times every $snooze seconds and am getting no response.\n\nI'm going to die now and hope that the next check works.\n\nThe last time I checked the IP was: $logged_ip\n";
close (MAIL);
exit;
} else {
print "\nDone sleeping and am tyring the check again...\n";
print "Counter is at: $counter\n";
$output = get $url;
}
}
print "Success! The check timed out $counter time(s) before finally returning a result: $output\n";
}
print "IP on record: $logged_ip\n";
#Compare the IPs and email if they're different
if ($logged_ip ne $output) {
print "The IP has changed, so I'm updating the IP log file and sending an email with the change\n";
print "The IP reported was $output\n";
open LOG, ">$file";
print LOG $output;
close LOG;
open (MAIL, "|/usr/sbin/sendmail -t ");
print MAIL "From: $from_addy\n";
print MAIL "To: $to_addy\n";
print MAIL "Content-Type: text/plain\n";
print MAIL "Subject: IP Address has changed to $output\n\n";
print MAIL "Your home IP Address has changed from $logged_ip to $output\n\nGo check DNS and fix if needed.\n";
close (MAIL);
} else {
#If the IP address hasn't changed, check the file age and email an update if it's over a week old - then update the file's time stamp
my $st = File::stat::stat($file);
my $age = time - $st->mtime;
my $days = int($age/(24*60*60));
my $hours = ($age/(60*60))%24;
my $mins = ($age/60)%60;
my $secs = $age%60;
my $how_old = "$days days, $hours hours, $mins minutes, $secs secs";
print "Age of the IP record file: $how_old\n";
if ($age > 604800) { #604800 is seconds/week - could variablize this if it was to change often
print "The IP is the same, but the log file is over a week old so I'm going to send an update\n";
open (MAIL, "|/usr/sbin/sendmail -t ");
print MAIL "From: $from_addy\n";
print MAIL "To: $to_addy\n";
print MAIL "Content-Type: text/plain\n";
print MAIL "Subject: Weekly Update: IP Address has NOT changed\n\n";
print MAIL "Your home IP Address has NOT changed in over a week and is still $output.\n\nThe file was this old: $how_old\n\n";
close (MAIL);
print "Mail sent.\n";
my $now = time;
utime $now, $now, $file;
print "File touched to update the timestamp.\n";
} else {
#If the IP's the same and it's been less than a week since the last email - don't do anything
print "The current IP ($logged_ip) matches the checked IP ($output) and it's been less than a week since the last send so there is nothing to do.\n";
}
}
1 Comment