chimni has asked for the wisdom of the Perl Monks concerning the following question:


Hi monks,
I was trying to write a snippet to ping multiple hosts(150) (fork implementation).
I want to store the min/avg/max ping response for each host in a file and if there is no response print NULL for that host.(along with gmt timestamps irrespective of the current machines zone settings)
2 ways i came across:
a)Article by merlyn dealing with the same.
b)Parallel::forkmanager
I read and used merlyn's article and came up with the following
#!/usr/bin/perl use strict; use warnings; my $timestamp=(`date -u +%Y-%m-%d,%T`); chomp($timestamp); print "$timestamp"; open(FI,">forkdata") || die ("Could not open file:$!"); sub ping_a_host { my $host = shift; @ping_output=`ping $host 16 -n 4 2>/dev/null`; if (grep { /round-trip\s+\(ms\)/ ; if ($_ =~ m#min/avg/max\s+=\s ++(\d+)/(\d+)/(\d+)#) {print FI "$host,$timestamp,$1,$2,$3\n"}} @ping +_output){ return 1;} elsif (grep {/0 packets rec/} @ping_output){ print FI "$host,$timestamp,NULL,NULL,NULL\n"; return 0; } } my %pid_to_host; sub wait_for_a_kid { my $pid = wait; return 0 if $pid < 0; my $host = delete $pid_to_host{$pid} or warn("Why did I see $pid ($?)\n"), next; warn "reaping $pid for $host\n"; 1; } my @hosts = map "192.198.192.$_", "221".."251"; for (@hosts) { wait_for_a_kid() if keys %pid_to_host > 10; if (my $pid = fork) { ## parent does... $pid_to_host{$pid} = $_; warn "$pid is processing $_\n"; } else { # child does ## child does... exit !ping_a_host($_); } } ## final reap: 1 while wait_for_a_kid(); close FI;

i get the desired output,but since i tampered with the script i was wondering if i unknowingly broke something or if there is a better way to do this.
code review anyone,any comments are welcome :)(asking to be shot)
regards,
chimni

Replies are listed 'Best First'.
Re: Ping multiple hosts (fork implementation)
by Juerd (Abbot) on Mar 09, 2004 at 16:41 UTC
Re: Ping multiple hosts (fork implementation)
by UnderMine (Friar) on Mar 09, 2004 at 16:27 UTC
    Number of processes generated will be twice the number of forks as the following shells out for the ping.
    @ping_output=`ping $host 16 -n 4 2>/dev/null`;
    Also this will be tainted. It might be worth looking at Net::Ping to reduce the processing load
    http://cpan.perl.org/authors/id/B/BB/BBB/Net-Ping-2.31.readme

    Is this having to go through a firewall because if you are not careful it may block you if you flood it with pings. Just because you can parallel the pings doesn't neccessarily meen the other end will like it.

    Hope it Helps
    UnderMine

Re: Ping multiple hosts (fork implementation)
by NetWallah (Canon) on Mar 09, 2004 at 17:03 UTC
    Hmm - your code is shell'ing out for dates and pings - not very perlish.

    This has been done in a more portable way , as discussed in the node "Non-blocking pings on Win32" (Which, is not specific to Win32).