AnyEvent и AnyEvent::Run на примере пинга нескольких устройств

Потребовалось пинговать несколько устройств в одной подсети. Эту задачу можно сделать в лоб, но мне захотелось через событийное программирование и модуль AnyEvent.

Идея следующая: запустить N процессов утилиты ping и через специальный метод обратного вызова получать строку вывода утилиты и выводить на экран.

Для асинхронной работы процессами был взят модуль AnyEvent::Run, как собрать deb пакет из cpan, можно почитать в журнале Pragmatic Perl(Сборка deb-пакетов модулей Perl для Debian и Ubuntu)

 

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;

use AnyEvent;
use AnyEvent::Run;

my @IPS = qw (
  ya.ru
  google.com
  mail.ru
);

my @HANDLERS;

my $cv = AnyEvent->condvar;

foreach my $ip (@IPS)
{
  my $handle = AnyEvent::Run->new(
    cmd      => [ 'ping', $ip, '-i 5' ],
    priority => 19,
    on_read  => sub {
      my $handler = shift;
      $handler->push_read(
        line => sub {
          my ( $hdl, $line ) = @_;
          say $line;
        }
      );
    }
  );

  push @HANDLERS, $handle;
}

$cv->recv;

on_read обратный вызов из AnyEvent::Handle который вызывается кода данные готовы для чтения, а очередь запросов на чтение пуста. push_read из того же AnyEvent::Handle добавляет обратный вызов на чтение данных, и определяет сколько необходимо данных для чтения. В данном случае устанавливается срабатывание на чтение одной строки.

Если запустить, то можно увидеть такую картину:

PING google.com (213.158.11.226) 56(84) bytes of data.
64 bytes from cache.google.com (213.158.11.226): icmp_seq=1 ttl=61 time=79.9 ms
64 bytes from cache.google.com (213.158.11.226): icmp_seq=2 ttl=61 time=49.4 ms
PING mail.ru (217.69.139.202) 56(84) bytes of data.
64 bytes from mail.ru (217.69.139.202): icmp_seq=1 ttl=55 time=90.7 ms
PING ya.ru (213.180.193.3) 56(84) bytes of data.
64 bytes from www.yandex.ru (213.180.193.3): icmp_seq=1 ttl=56 time=93.9 ms
64 bytes from mail.ru (217.69.139.202): icmp_seq=2 ttl=55 time=82.2 ms
64 bytes from www.yandex.ru (213.180.193.3): icmp_seq=2 ttl=56 time=106 ms
64 bytes from cache.google.com (213.158.11.226): icmp_seq=3 ttl=61 time=140 ms
64 bytes from mail.ru (217.69.139.202): icmp_seq=3 ttl=55 time=98.7 ms
64 bytes from www.yandex.ru (213.180.193.3): icmp_seq=3 ttl=56 time=97.5 ms
64 bytes from cache.google.com (213.158.11.226): icmp_seq=4 ttl=61 time=98.4 ms
64 bytes from mail.ru (217.69.139.202): icmp_seq=4 ttl=55 time=126 ms
64 bytes from www.yandex.ru (213.180.193.3): icmp_seq=4 ttl=56 time=151 ms
64 bytes from cache.google.com (213.158.11.226): icmp_seq=5 ttl=61 time=112 ms