Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > пинг целой подсети


Автор: fedottt 17.1.2010, 22:24
наваял вот такое...
сделано для пингования вагона ip (порядка 6к)
скрипт должен брать из базы и туда же скидывать результат пинга. 
необходимо для мониторинга. на данный момент лучшего решения с использованием БД Mysql не придумал ((
короче говоря, у меня этот костыль отрабатывает первые 400 хостов как положено, а потом где-то зацикливается и поедает всю память на сервере. сьел 10 гиг и уложил систему.

можете глянуть, где я допустил ошибку? 
чуствую что метод написания скриптов а-ля php в перле не канает.. 

должен был делать такое:
взял в базе 400 ip, на них склепал 400 нитей, выполнил, взял следующие 400, нити и так далее..
но где-то затык(

Код

#!/usr/bin/perl
use Benchmark;
use DBI;
use Net::Ping;
use threads;

$db="ping";
$host="localhost";
$userid="user";
$passwd="pass";
$connectionInfo="dbi:mysql:$db;$host";

$dbh = DBI->connect($connectionInfo,$userid,$passwd);

for($g=0;$g<18;$g++){

    # чистим
    unlink ("LOG");
    unlink ("LOG2");

    $#hz = -1;
    $#hzz = -1;
    $#arr_ip = -1;
    $#arr_i = -1;
    $#threads = -1;

    $sec=$sec+400;
    if($i!=0){$fir=$sec-399;}else{$fir=0;}


    # запрос на выборку
    $query = "select ip as HOST from users limit $fir,$sec";
    $sth = $dbh->prepare($query);
    $sth->execute();
    $sth->bind_columns(\$HOST);


    while ($pf=$sth->fetchrow_hashref){
        $hzz.=$pf->{HOST}."|";
    }

    @hz=split(/[|]/,$hzz);


    for ($i=0; $i<=$#hz; $i++) {
        push @threads, threads->create(\&pong, $hz[$i]);
    }


foreach $thread (@threads) {
        $thread->join();
    }
    
sub pong {
    $time1 = new Benchmark;
    my $sdp = Net::Ping->new("icmp",1,1);
    if ($sdp->ping($hz[$i])){
        open(F1,">> LOG");
        print (F1 "$hz[$i]\n");
        close (F1);
        
        open(F2,">> LOG2");
        print (F2 "1\n");
        close (F2);
    }else{
        open (F1,">> LOG");
        print (F1 "$hz[$i]\n");
        close (F1);

        open (F2,">> LOG2");
        print (F2 "0\n");
        close (F2);
    }
    open(FILE, "<", "LOG");
    while(<FILE>) {
        chomp;
        push(@arr_ip, $_);
        #print "array element: $_\n";
    }
    close(FILE);
    open(FILE2, "<", "LOG2");
    while(<FILE2>) {
        chomp;
        push(@arr_i, $_);
        #print "array element: $_\n";
    }
    close(FILE2);
    
    for($t=0; $t<=$#arr_ip; $t++){
        #print "update users set ping=$arr_i[$t] where ip=$arr_ip[$t]\n";
        open (FF1,">> LOG2ALL");
        print (FF1 "$t -- update users set ping=$arr_i[$t] where ip=$arr_ip[$t]\n");
        close (FF1);
    }
    
    $time2 = new Benchmark;
    $timebenchmark = timediff($time1, $time2);
    print "Time", timestr($timebenchmark);
    
}
   }               
;


Автор: mvsgt 18.1.2010, 02:25
Ошибка в подходе. Пинговать надо с помощью nmap, а для мониторинга использовать специальные программы.

Скрипт сначала следовало бы сократить раза в 2 за счёт использования File::Slurp для записи в файлы, потом use strict; добавить, а без него искать ошибки - себя не уважать, уж извините.

PS 

C потоками Вы как-то вольно работаете, с переменными как будто они общие. Замыкания чуть-чуть исправляют ситуацию, но глюков это только прибавляет. И вообще такое ощущение, что программа не на перле написана. use strict обязательно добавляйте, сразу поёмёте что написали какую-то жуть.

Автор: DurRandir 18.1.2010, 06:41
Не используйте потоки. Потоки в перл - зло. Посмотрите на AnyEvent::FastPing, и вообще event-driven подход как полную замену потокам при работе с сетью.

PS: у вас, конечно, странный код, но это пройдёт smile Из явных ошибок - запись/чтение в лог-файл не синхронизирована (а чтение - вообще непонятно зачем), если 2 потока будет писать одновременно, то будет мусор.

Автор: krypt3r 18.1.2010, 06:47
Цитата

Пинговать надо с помощью nmap

+1, зачем вЕлики клепать
Код

$ nmap -sP 192.168.1.1/24

Про use strict из перл-кодеров вообще единицы знают

Автор: amg 18.1.2010, 07:02
К старым версиям Net::Ping прилагалась программа
fping - pings multiple hosts at once
Ее можно найти на CPAN и пользоваться (или взять из нее распаралеливающий код).

Автор: fedottt 18.1.2010, 16:46
nmap решил вопрос)))
спасибо вам)

код у меня такой кривой, бо привык в php. perl пока не дается.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)