On 05/12/11 14:57, Phil Stracchino wrote:
> This is version 2.0 of my checkhost tool.
Except that somehow I accidentally attached the wrong version. Let's
try this again.
To make up for the error, here's a standalone lanwake tool using the
same DB backend as well.
--
Phil Stracchino, CDK#2 DoD#299792458 ICBM: 43.5607, -71.355
ala...@caerllewys.net ala...@metrocast.net p...@co.ordinate.org
Renaissance Man, Unix ronin, Perl hacker, SQL wrangler, Free Stater
It's not the years, it's the mileage.
#!/usr/bin/perl
#
# checkhost version 2.0 by Phil Stracchino
# All rights assigned to the Bacula project
# Licensed under the GPL v2, or at your option any later version
#
# Check whether a bacula client is alive and responding on the network.
# Optionally, send a wake-on-LAN packet to the client before testing.
#
# Checkhost does not perform a Bacula connection handshake or verify
# that passwords match; it only verifies that the client is reachable
# on the network and responding, and that the Bacula client is running
# and listening on port 9102.
#
# Usage: checkhost [-r] [-v] [-i seconds] hostname|ipaddress
# Options:
# -r, --retry: Try three times to connect (default: try only once)
# -i, --interval: Specify time in seconds to wait between retries
# (default: 30 seconds)
# -v, --verbose: output verbose status messages, for interactive
# use (default: operate silently)
# -w, --wake: send wake-on-LAN packet before trying to connect
#
# Wake-on-LAN functionality requires the following schema to be created, by
# default, with a correct authentication group set up in .my.cnf for the
# group Bacula runs as:
# CREATE DATABASE ethers;
# CREATE TABLE ethers.ethers (id int primary key auto_increment,
# hostname varchar(128),
# ethers varchar(128),
# index host (hostname));
# The hostname field should contain a short or fully qualified hostname,
# while the ethers field should contain a list of hardware MAC addresses
# for that host, separated by spaces.
use strict;
use Getopt::Long;
use DBI;
use Socket;
use Net::Ping;
use Net::Telnet ();
# Return values:
# -1 Program error or no host specified
# 0 Success, FD found and responding
# 1 Client alive but FD not listening
# 2 Client not found on network
my $ret = -1;
my ($etherdb, $ethergroup) = qw(ethers ethers);
my $broadcast = '10.24.32.255';
my $my_ip = '10.24.32.14';
my ($host, %opts);
die "You must set the broadcast and my_ip addresses before running this tool"
unless ($my_ip);
Getopt::Long::Configure ("bundling");
GetOptions(\%opts,
'interval|i=i',
'retry|r',
'verbose|v',
'wake|w');
$host = shift || die "No host specified!\n";
$ret = check_host($host) if ($host);
print "Client $host not found on network\n" if ($ret == 2);
print "Returning value $ret\n" if ($opts{verbose});
exit ($ret);
sub check_host
{
my $host = $_[0];
my ($hostname, $p, $retrycount);
if ($host =~ /^\d+\.\d+\.\d+\.\d+$/)
{
my $ip = inet_aton($host);
$hostname = gethostbyaddr($ip, AF_INET);
print "Host $host has name $hostname\n" if ($opts{verbose});
}
else
{
$hostname = $host;
printf("Client $host has address %d.%d.%d.%d\n",
unpack('C4',
(my @addrs = (gethostbyname($host))[4])[0]));
}
if ($opts{wake})
{
foreach my $ether (split(/\s+/, get_ethers_by_host(shift())))
{
wake_host_by_hwaddr($ether);
}
printf("Wake-on-LAN packet sent to $host; sleeping for %s seconds\n",
$opts{interval} || 30) if ($opts{verbose});
sleep ($opts{interval} || 30);
}
$p = Net::Ping->new("icmp");
$p->bind($my_ip);
$retrycount = ($opts{retry} ? 3 : 1);
while ($retrycount && ($ret != 0))
{
if ($p->ping($host, 2))
{
print "Host $host is alive\n" if ($opts{verbose});
my $t = new Net::Telnet (Timeout => 10,
Port => 9102,
Prompt => '/bash\$ $/');
if ($t->open($host))
{
print "Bacula-FD listening on port 9102\n" if ($opts{verbose});
$ret = 0;
}
else
{
print "Bacula-FD not running on host $host\n";
$ret = 1;
}
$t->close;
}
else
{
$ret = 2;
}
$retrycount--;
if ($opts{retry} && ($ret != 0))
{
printf("\tNot found on try %d",
3 - $retrycount) if ($opts{verbose});
if ($retrycount)
{
printf("; sleeping for %s seconds before retrying\n",
$opts{interval} || 30) if ($opts{verbose});
sleep($opts{interval} || 30);
}
else
{
print "\n" if ($opts{verbose});
}
}
}
$p->close();
return ($ret);
}
sub wake_host_by_hwaddr
{
my ($packet, $hwaddr, $raddr, $port);
foreach (split /:/, $_[0])
{
$hwaddr .= chr(hex($_));
}
$packet = chr(0xFF) x 6 . $hwaddr x 16;
socket((SOCK, AF_INET, SOCK_DGRAM, getprotobyname('udp'))) || die "socket :
$!";
setsockopt(SOCK, SOL_SOCKET, SO_BROADCAST, 1) || die "setsockopt : $!";
$port = getservbyname('discard', 'udp');
$raddr = gethostbyname($broadcast);
send(SOCK, $packet, 0, pack_sockaddr_in($port, $raddr)) || die "send : $!";
close (SOCK);
return;
}
sub get_ethers_by_host
{
my ($dbh, $sth, $query, $ethers);
$dbh = open_db();
$query = sprintf('SELECT ethers FROM ethers WHERE hostname = \'%s\'',
$_[0]);
$sth = $dbh->prepare($query);
$sth->execute || die "Error:" . $dbh->errstr . "\n";
while (my $ref = $sth->fetchrow_arrayref)
{
$ethers = $$ref[0];
}
$sth->finish();
$dbh->disconnect();
return ($ethers);
}
sub open_db
{
my $home = $ENV{'HOME'};
my ($dsn, $dbh, $user, $password);
$dsn = "DBI:mysql:database=$etherdb;"
. "mysql_read_default_group=$ethergroup;"
. "mysql_read_default_file=$home/.my.cnf;"
. "mysql_mysql_client_found_rows=TRUE;"
. "mysql_mysql_ssl=TRUE";
$dbh = DBI->connect($dsn, undef, undef, {RaiseError => 1, AutoCommit => 0});
return ($dbh);
}
#!/usr/bin/perl
use strict;
use DBI;
use Socket;
foreach my $ether (split(/\s+/, get_ethers_by_host(shift())))
{
wake_host_by_hwaddr($ether);
}
exit (0);
sub wake_host_by_hwaddr
{
my ($packet, $hwaddr, $raddr, $port);
foreach (split /:/, $_[0])
{
$hwaddr .= chr(hex($_));
}
$packet = chr(0xFF) x 6 . $hwaddr x 16;
socket((SOCK, AF_INET, SOCK_DGRAM, getprotobyname('udp'))) || die "socket :
$!";
setsockopt(SOCK, SOL_SOCKET, SO_BROADCAST, 1) || die "setsockopt : $!";
$port = getservbyname('discard', 'udp');
$raddr = gethostbyname('255.255.255.255');
send(SOCK, $packet, 0, pack_sockaddr_in($port, $raddr)) || die "send : $!";
close (SOCK);
return;
}
sub get_ethers_by_host
{
my ($dbh, $sth, $query, $ethers);
$dbh = open_db();
$query = sprintf('SELECT ethers FROM ethers WHERE hostname = \'%s\'',
$_[0]);
$sth = $dbh->prepare($query);
$sth->execute || die "Error:" . $dbh->errstr . "\n";
while (my $ref = $sth->fetchrow_arrayref)
{
$ethers = $$ref[0];
}
$sth->finish();
$dbh->disconnect();
return ($ethers);
}
sub open_db
{
my $home = $ENV{'HOME'};
my ($dsn, $dbh, $user, $password);
$dsn = "DBI:mysql:database=ethers;"
. "mysql_read_default_group=ethers;"
. "mysql_read_default_file=$home/.my.cnf;"
. "mysql_mysql_client_found_rows=TRUE;"
. "mysql_mysql_ssl=TRUE";
$dbh = DBI->connect($dsn, undef, undef, {RaiseError => 1, AutoCommit => 0});
return ($dbh);
}
------------------------------------------------------------------------------
Achieve unprecedented app performance and reliability
What every C/C++ and Fortran developer should know.
Learn how Intel has extended the reach of its next-generation tools
to help boost performance applications - inlcuding clusters.
http://p.sf.net/sfu/intel-dev2devmay
_______________________________________________
Bacula-users mailing list
Bacula-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bacula-users