Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
Hi Peeps,
I have wrote the following code, it works, but it is laim coding. Would someone show me a better way of writing this (or parts of this) script.
#!/usr/bin/perl
use IO::Socket::INET;
$time = localtime;
$users = grep{ -d $_ } glob('/home/*');
$users = $users + 600;
$mx1pop3 = IO::Socket::INET->new(
Timeout => 1,
PeerAddr => 'mail.test.com',
PeerPort => 110,
Proto => 'tcp');
$mx1smtp = IO::Socket::INET->new(
Timeout => 1,
PeerAddr => 'mail.test.com',
PeerPort => 25,
Proto => 'tcp');
$mx1web = IO::Socket::INET->new(
Timeout => 1,
PeerAddr => 'test.com',
PeerPort => 80,
Proto => 'tcp');
$mx1dns = IO::Socket::INET->new(
Timeout => 1,
PeerAddr => 'test.com',
PeerPort => 53,
Proto => 'tcp');
if ($mx1pop3 and $mx1smtp) {
$mail = 'Up';
} else {
$mail = 'Down';
}
if ($mx1web) {
$web = 'Up';
} else {
$web = 'Down';
}
if ($mx1dns) {
$dns = 'Up';
} else {
$dns = 'Down';
}
print "Content-type: text/html\n\n";
print "<p><font size=1 face=Arial, Helvetica, sans-serif>$time</font><
+/p>\n" ;
print "<p><font size=1 face=Arial, Helvetica, sans-serif>Mail Servers:
+ $mail<br>Web Servers: $web<br>DNS Servers: $dns</font></p>\n" ;
print "<p><font size=1 face=Arial, Helvetica, sans-serif>Active Users:
+ $users</font></p>\n" ;
Re: My Code Is Functional...But Not Tidy :(
by grep (Monsignor) on Apr 23, 2003 at 17:46 UTC
|
This is a little cleaner, but I would recommend not reinventing the wheel. Nagios is an excellent system monitoring product.
#!/usr/local/bin/perl
use strict;
use warnings;
use IO::Socket::INET;
my %config = (
'mail.test.com' => [ 'smtp','pop3' ],
'localhost' => [ 'http','dns' ]
);
my %check;
foreach my $host (keys %config) {
foreach my $port (@{$config{$host}}) {
my $host_port = "$host".'_'."_$port";
$check{$host_port} = IO::Socket::INET->new(
Timeout => 1,
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
}
}
foreach my $check_it (keys %check) {
if ($check{$check_it}) {
print "$check_it is ok\n";
}
}
grep
Mynd you, mønk bites Kan be pretti nasti... |
| [reply] [d/l] |
•Re: My Code Is Functional...But Not Tidy :(
by merlyn (Sage) on Apr 23, 2003 at 17:50 UTC
|
The core testing part can be something like:
use IO::Socket::Inet;
for (
['Mail Servers', 'mail.test.com:110', 'mail.test.com:25'],
['Web Servers', 'test.com:80'],
['DNS Servers', 'test.com:53'],
) {
my ($message, @ports) = @$_;
my $good = 1;
for (@ports) {
$good = 0, last unless IO::Socket::INET->new($port);
}
print "$message: ", $good ? "Up" : "Down";
print "\n";
}
You'll have to add the HTML yourself. {grin}
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply. | [reply] [d/l] |
Re: My Code Is Functional...But Not Tidy :(
by pfaut (Priest) on Apr 23, 2003 at 17:47 UTC
|
#!/usr/bin/perl -w
use strict;
use IO::Socket::INET;
my %services = ( pop => [ 'mail.test.com', 110 ],
smtp => [ 'mail.test.com', 25 ],
web => [ 'test.com', 80 ],
dns => [ 'test.com', 53 ],
);
my %status;
$status{$_} = 'Up' for keys %services;
while (my ($name,$svc) = each %services) {
my $sock = IO::Socket::INET->new(Timeout=>1,
PeerAddr => $svc->[0],
PeerPort => $svc->[1],
Proto => 'tcp' )
or $status{$name} = 'Down';
}
while (my ($name,$sts) = each %status) {
print "$name server is $sts\n";
}
90% of every Perl application is already written. ⇒ | dragonchild |
| [reply] [d/l] |
Re: My Code Is Functional...But Not Tidy :(
by dragonchild (Archbishop) on Apr 23, 2003 at 17:48 UTC
|
Just replacing the middle part:
# Above all others, add:
use strict;
# Some stuff here
my %connection = (
pop3 => {
PeerAddr => 'mail.test.com',
PeerPort => 110,
},
# Add the others here, like above
);
my %socket;
while (my ($name, $values) = each %connections)
{
$socket{$name} = IO::Socket::INET->new(
Timeout => 1,
Proto => 'tcp',
( map { $_ => $values->{$_} } keys %$values ),
);
}
my $UP = 'Up';
my $DOWN = 'Down';
my $mail = ($socket{pop3} && $socket{smtp}
? $UP
: $DOWN);
# Do other checks here
Oh - use CGI::Lite for your HTML outputting, or, better, use HTML::Template. Always try to separate presentation from logic.
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement. Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified. | [reply] [d/l] |
Re: My Code Is Functional...But Not Tidy :(
by Trimbach (Curate) on Apr 23, 2003 at 17:51 UTC
|
Ugliness is in the eye of the beholder. There's lots and lots (and lots) of different ways to do it.. I'd probably use a hash-of-hashes, but hey, what you've got works, it's easy to maintain, and it is brutally clear what it does and how it does it. TMTOWTDI, and all that.
Personally I wouldn't sweat it unless you were planning on vastly expanding this program, or were trying to make it into a more generalized solution, and if that's the case you're definitely in wheel-reinvention territory. :-)
Gary Blackburn
Trained Killer | [reply] |
Re: My Code Is Functional...But Not Tidy :(
by Solo (Deacon) on Apr 23, 2003 at 20:24 UTC
|
#!/usr/bin/perl
use IO::Socket::INET;
use Config::IniFiles;
my $cfg = Config::IniFiles->new(-file => *DATA);
my %socket = ();
for my $monitor ( $cfg->GroupMembers('Monitor') ) {
my ($name) = $monitor =~ /Monitor (.+)/;
$socket{$name} = IO::Socket::INET->new(
Timeout => $cfg->val( $monitor, 'Timeout' ),
PeerAddr => $cfg->val( $monitor, 'PeerAddr' ),
PeerPort => $cfg->val( $monitor, 'PeerPort' ),
Proto => $cfg->val( $monitor, 'Proto' ),
);
}
# ...
__DATA__
[Monitor Pop3]
Timeout = 1
PeerAddr = 'mail.test.com'
PeerPort = 110
Proto = 'tcp'
[Monitor SMTP]
Timeout = 1
PeerAddr = 'mail.test.com'
PeerPort = 25
Proto = 'tcp'
[Monitor Web]
Timeout = 1
PeerAddr = 'test.com'
PeerPort = 80
Proto = 'tcp'
[Monitor DNS]
Timeout = 1
PeerAddr = 'test.com'
PeerPort = 53
Proto = 'tcp'
Naturally, the DATA filehandle could (should) be replaced with a real file--and you magically gain the benefit of multiple configurations. Not to mention all the bells & whistles of IniFiles, like defaults and updates.
Update: fixed small typo
--Solo
--
You said you wanted to be around when I made a mistake; well, this could be it, sweetheart.
| [reply] [d/l] |
Re: My Code Is Functional...But Not Tidy :(
by Fletch (Bishop) on Apr 23, 2003 at 19:21 UTC
|
| [reply] |
Re: My Code Is Functional...But Not Tidy :(
by Anonymous Monk on Apr 24, 2003 at 17:02 UTC
|
This is the perfect moment for a Factory pattern. Write a function that returns IO::Socket::Inet objects, but you only pass the parameters along.
Your factory, is an engine of sorts. How it figures out what object you want is up to you. You can make configuration files, as someone suggested and your factoury would do, Factory->new( 'http://test.com' ) for port 80, or Factory->new('smtp://test.com').
Or you can write a Factory that takes all the parameters.
All in all, it'd reduce the code down to ...
$web = Factory->new( some parameters, a url, or numbers and hosts );
$smtp = ....
$something = ....
But otherwise, it's not THAT ugly in truth. YOu formated your code, it's easy to read. The factory thing is all i can really suggest. | [reply] |
|
Isn't that what IO::Socket::Inet::new is already doing?
I don't see how your factory method would be doing anything different. And for what it's worth, the original poster's code is some of the cleanest Perl I've ever seen.
| [reply] |
|
Well, if you integrate configuration files into the factory, your code becomes cleaner. Now lets say you stop using IO::Socket::Inet but switch to something else, you don't have to change from using IO::Socket everywhere, just change how the factory works.
| [reply] |
|
It is clean, yes. But, it's not very extensible, configurable, or customizable. It doesn't take advantage of shared snippets to make maintenance easier. That's what most of the responses have been about. Taking it to the next level, if that's what's desirable and desired.
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement. Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.
| [reply] |
|
|