Home > Archive > PERL Beginners > May 2007 > Watchdog script with IO::Socket
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Watchdog script with IO::Socket
|
|
| jrpfinch 2007-05-16, 6:59 pm |
| I've written a proof-of-concept script that listens on a unix socket
and raises an alarm if it is not sent all the numbers from 1-60 every
60 seconds. I am newish to Perl, completely new to sockets, have done
a little RTFM and would welcome any comments on the script (#####
SERVER #####). I include a ###### CLIENT ####### script below that to
send the numbers 1-20,22-60 every fifty seconds so you can test it
out. It seems wrong that I should have to fork off a client in the
####SERVER#### script to kick it every second, but I have yet to come
up with a more elegant solution. Many thanks, Jon.
######## SERVER #########
#!/usr/local/bin/perl
use warnings;
use strict;
use IO::Socket;
unlink "/tmp/sckt";
#-------------------------------------------------------------------------------
# Initialise hash
#-------------------------------------------------------------------------------
my %watchHash;
for (1..60)
{
$watchHash{$_} = 0;
}
#-------------------------------------------------------------------------------
# Initialise time reference point
#-------------------------------------------------------------------------------
my $timeDatum = time();
#-------------------------------------------------------------------------------
# Fork - parent process is listening for connections
# - child process is printing to socket once per second to force
the while
# loop
#-------------------------------------------------------------------------------
my $pid = fork();
# Parent
if ($pid)
{
my $Server = IO::Socket::UNIX->new( Local => "/tmp/sckt",
Type => SOCK_STREAM,
Listen => 5) or die "$!\n
$@";
while(my $session = $Server->accept)
{
#-------------------------------------------------------------------------
# After 60 seconds elapsed, check to see that all keys in
%watchHash
# are set to true. Print message if any are false. Reset
timeDatum.
#-------------------------------------------------------------------------
if (time() > $timeDatum + 60)
{
$timeDatum = time();
for (1..60)
{
if ($watchHash{$_} == 0)
{
print "Alarm for $_\n";
}
else
{
$watchHash{$_} = 0;
}
}
}
#-------------------------------------------------------------------------
# Deal will client connections, ignore polls from child
#-------------------------------------------------------------------------
while (my $line = <$session> )
{
last if $line eq "poll\n";
chomp ($line);
$watchHash{$line} = 1;
}
$session->close();
}
}
# Child
elsif ($pid == 0)
{
# Sleep for 5 seconds to ensure server has started
sleep(5);
while (1)
{
#-------------------------------------------------------------------------
# Create a new session each time, otherwise while in server will
never
# loop
#-------------------------------------------------------------------------
my $socket = IO::Socket::UNIX->new( Peer => "/tmp/sckt",
Type => SOCK_STREAM,
Timeout => 10 ) or die "$!\n$@";
next unless $socket;
$socket->print("poll\n");
$socket->flush();
$socket->close();
sleep(1);
}
exit(0);
}
########### MULTIPLE CLIENT EMULATOR ##############
#!/usr/local/bin/perl
use strict;
use warnings;
use IO::Socket;
my $num;
megaHit();
sub megaHit
{
while (1)
{
my @childs;
for(1..20,22..60)
{
$num = $_;
my $pid = fork();
if ($pid)
{
# parent
push(@childs, $pid);
}
elsif ($pid == 0)
{
# child
my $socket = IO::Socket::UNIX->new( Peer => "/tmp/sckt",
Type => SOCK_STREAM,
Timeout => 10 ) or die "$!\n$@";
$socket->print("$num\n");
$socket->flush();
exit(0);
}
else
{
die "couldn't fork: $!\n";
}
}
foreach (@childs)
{
waitpid($_, 0);
}
sleep(50);
}
}
| |
| usenet@DavidFilmer.com 2007-05-16, 6:59 pm |
| On May 16, 10:33 am, jrpfinch <jrpfi...@gmail.com> wrote:
> #-------------------------------------------------------------------------------
> # Initialise hash
> #-------------------------------------------------------------------------------
> my %watchHash;
> for (1..60)
> {
> $watchHash{$_} = 0;
>
> }
FWIW, I just glanced at your code and noticed this construct, and I
couldn't resist sharing this handy and elegant little idiom that I
picked up from Damian Conway's "Perl Best Practices" (page 272):
my %watchhash = map{ ($_ => 0) } (1..60);
BTW, if you are newish to Perl, you really should pick up a copy of
_PBP_ (it's the second Perl book anyone should ever buy).
--
The best way to get a good answer is to ask a good question.
David Filmer (http://DavidFilmer.com)
| |
| Uri Guttman 2007-05-16, 6:59 pm |
| >>>>> "u" == usenet <usenet@DavidFilmer.com> writes:
i haven't even looked at the OP's code. this is just about the hash
init stuff.
[color=darkred]
u> FWIW, I just glanced at your code and noticed this construct, and I
u> couldn't resist sharing this handy and elegant little idiom that I
u> picked up from Damian Conway's "Perl Best Practices" (page 272):
u> my %watchhash = map{ ($_ => 0) } (1..60);
you don't need the parens on the 1 .. 60 part. this is another way to do
that:
my %watchhash ;
@watchhash{ 1..60 } = (0) x 60 ;
but i am wary of any hash that uses a sequential set of numbers for its
keys. that screams out array. to do this with an array you would code:
my @watch ;
done!
you can count up with ++ (hell, the hash didn't need to be initialized
to 0's if it was just used for counting either) and it will do just
fine.
uri
--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
|
|
|
|
|