Reputation: 181
I'm trying to create a perl module that pings (using the linux system ping) to hundreds of hosts, and get the data of the ping (like packet loss and how much packets transmitted and how much received and etc.) from the stdout of each host. I used AnyEvent::Util fork_call, but I got stuck as it doesn't collect the stdout. I've created a small script that demonstrates what i'm trying to do:
#!/usr/bin/perl
use strict;
use warnings;
use AnyEvent;
use AnyEvent::Util 'fork_call';
use DDP;
my $cv = AE::cv;
my @hosts = ( 'google.com', 'xkcd.com', 'pastebin.com', 'youtube.com' );
sub fork_ping {
my $interval = 0.2;
my $source_address = '1.1.1.1';
my $number_of_pings = 5;
my $timeout = 5;
my %ret_val;
foreach my $host (@hosts) {
$cv->begin;
fork_call {
my $stdout = `ping -c $number_of_pings -I $source_address -i $interval -W $timeout $host 2>&1`;
return $stdout;
} sub {
$ret_val{$host} = shift;
$cv->end;
};
}
return \%ret_val;
}
my $timer = AE::timer 0, 5, sub {
my $ping_data = fork_ping();
p $ping_data;
};
$cv->recv;
Where have I got wrong?
Upvotes: 4
Views: 830
Reputation: 2204
Don't call an external program if you can solve it with Perl too. It will make your app depend on the availability of the ping command, it's API (CLI parameter names, order, format) and its output format that might change.
I use POE::Component::Client::Ping successfully since years to monitor thousands of our network devices.
Upvotes: 1
Reputation: 386331
You need to wait for the pings to finish ($cv->recv;
) before you can print their output.
my $ping_data = fork_ping();
$cv->recv;
p $ping_data;
(You could also place the $cv->recv;
inside of fork_ping
.)
Upvotes: 3