Adamba4
Adamba4

Reputation: 181

AnyEvent fork_call and ping

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

Answers (2)

Alexander Hartmaier
Alexander Hartmaier

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

ikegami
ikegami

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

Related Questions