Saturday, January 31, 2009

Ping or die

So, we've got this computer that we use as a router... and since it probably eats electricity like crazy, compared to an ordinary router, every night when everyone goes off-line somebody has to turn it off. And since programmers are lazy, we've been kicking around the idea of making a program that turns the damn thing off by itself.

But since programmers are lazy, I only did it today, after a year of excuse finding (at which I am highly proficient).

Result: here's a little Perl script to run commands when some computers go off-line. It turned out quite simple. Enjoy!

 
1 #!/usr/bin/perl
2 #
3 # Ping or die
4 #
5 # Pings all ip addresses and turns off the machine when
6 # all of them are dead.
7 # If you need to run other commads, you can do that too.
8 #
9 # Parameters:
10 # c - command to run,
11 # s - sleep time between pinging (in seconds),
12 # t - ping timeout (in seconds),
13 # IP addresses or hostnames to watch.
14 # Example:
15 # Turn on the Rokudan when the router's down for a minute:
16 # ping_or_die -s 60 "mpg321 Rokudan.mp3" 10.0.0.2
17 # Author:
18 # Konrad Siek
19
20 # Packages
21 use Net::Ping;
22 use Getopt::Std;
23
24 # Defaults
25 my $command = "shutdown -h now";
26 my $sleep_time = 300;
27 my $timeout = 10;
28 my $hosts = ();
29
30 # Setup options
31 my %options = ();
32 getopt "cst", \%options;
33 $command = @options{c} if defined @options{c};
34 $sleep_time = @options{s} if defined @options{s};
35 $timeout = @options{t} if defined @options{t};
36 @hosts = @ARGV;
37
38 # If no hosts were provided print help and exit.
39 if (scalar @hosts < 1) {
40 print "Usage: $0 [options] list-of-ips\n";
41 print "\t-c\tcommand to run\n";
42 print "\t-s\tsleep time between pinging (in seconds)\n";
43 print "\t-t\tping timeout (in seconds)\n";
44 exit -1;
45 }
46
47 # Setup ping - 30 second timeout
48 $ping = Net::Ping->new("tcp", $timeout);
49
50 # Main program
51 my $again;
52 do {
53 $again = 0;
54 # Wait some time before checking
55 sleep $sleep_time;
56 # Ping machines
57 foreach (@hosts) {
58 my $present = $ping->ping($_);
59 $again |= $present;
60 }
61 } while ($again);
62
63 # Finish up ping
64 $ping->close();
65
66 # Info
67 print "$0: dead hosts: @hosts\n";
68 print "$0: running command '$command'\n";
69
70 # Run command
71 system $command;
72


The code is also available at GitHub as perl/ping_or_die.

1 comment:

Wesley Levels said...

Thanks. Gonna use this one as a start for creating a script to power my ESXi vms down on power failure (when APC takes over with lifetime of about 20 minutes)

greets Wesley!