Forum Webscript.Ru
Программирование => Perl => Тема начата: AnnA от 09 Ноября 2004, 15:56:17
-
Всем приветик.
Умные дяденьки, помогите мне пожалуйста разобраться в этом лесу.
Ну никак что-то я не пойму, что там к чему.
Купила умную книжку, там расписано как использовать модуль Thread и всё бы хорошо, но он даже не установлен у меня такой на хостере к тому же хотелось бы научиться делать ЭТО сначала на fork. :)
Вот написано мол так и так, обязательно дескать используйте:#!/usr/bin/perl -Tw
use strict;
[b]use sigtrap;[/b]
use Socket;
А мне и не жалко. Написано, значит так надо. Написала, делов-то. Только не совсем понятно - зачем? Куда его потом пихать этот $SIG{PIPE} = \'IGNORE\';?
Или я вообще что-то напутала?
Вот у меня есть, например, такая задача: нужно скажем с десяти разных адресов забрать модулем LWP по два-три документа (адреса и имена документов известны). В самом обычном текстовом файле лежат данные по строчкам: адрес, имя документа. Код не нужен - просто сама идея. :)
читаю я файл в массив(он небольшой - 10 строчек всего), а вот теперь самое для меня трудное, - как мне сделать несколько процессов. Т.е. по одному документику в цикле я получаю их все, но это очень уж долго. :(
Просто делаю for для массива, split\'ом достаю адрес, имя документа. Получила, следующий... Примитивно до обидного. :) Ой. Забыла. Сначала я пингую каждый адрес Net::Ping. Если есть пинг - забираю документ, пинга нет - next;
В общем идея такая:foreach (@massiv) {
my ($server,$port,$doca) = split... достаем данные
if ($pid = fork) {
$p=ping->$server
if ($p) { #пинг получен - сервер жив
#запрашиваем $server:80/$doca при помощи LWP, делаем с ним чего-то;
} #EO if($p)
else {print $server,\'не отвечает\';}
waitpid($pid,0);
} else {
die "cannot fork: $!" unless defined $pid;
exit;
} #EO if ($pid = fork)
} #EO foreach (@massiv)
ужас, да? :(
Подскажите пожалуйста, как правильно а?
Целое письмо написала. :)
-
AnnA
1) пинг выносим за пределы форка. незачем нам форкаться а только потом проверять доступность.
2) прироста скорости ты не получишь, потому как в этой схеме ты будешь ждать завершения первого форка, затем второго и так далее.
Идея проста, но не очень красива: форкаться и отдавать управление внешнему(второму скрипту) через exec.
AnnA:
Куда его потом пихать этот $SIG{PIPE} = \'IGNORE\';?
С сигналами нужно вести очень осторожно и использовать их только тогда, когда понимаешь что они должны делать.
В данном случае его пихать никуда не нужно.
-
NeoNox пасиба большое. :)
NeoNox:
пинг выносим за пределы форка.
разве не будет быстрее, если будут пинговаться сразу несколько серверов, а не каждый по очереди?
я так и думала, что вся итерация foreach будет делиться скажем на 5 потоков, т.е. в идеале скрипт должен работать в 2 раза быстрее? нет? А как мне управлять количеством потоков? Где-то надо ставить счетчик, который, например, если ==5, то ждём завершения 1-го потока и вновь идём по кругу с 1-го по 5-й. Т.е. что бы их было не более 5. Или такое невозможно?
NeoNox:
Идея проста, но не очень красива: форкаться и отдавать управление внешнему(второму скрипту) через exec.
ага. :) поняла. спасибо.
А, если красиво (хотя бы просто красиво, а не очень пока) - надо всё таки через Thread делать?NeoNox:
В данном случае его пихать никуда не нужно.
Хорошо. :) Я тут же забыла про эти сигналы. ;)
-
AnnA:
надо всё таки через Thread делать?
Да. Это будет правильнее.
AnnA:
в идеале скрипт должен работать в 2 раза быстрее? нет?
в идеале да, но не в твоем случае.
напиши на бумажке что, как и когда у тебя происходит в этой программе.
выведи отладку вместе со временем исполнения и ты увидишь о чем я говорю.
-
:confused: Не работает. :insane:
тихохонько так раз. и умирает, и еррор.лог пустенький совершенно вот что обидно. :(
Может вы мне чего-то недоговариваете? :)
Поглядите, если не сложно:open(D,"<","$servers") or die "Can\'t read $servers: $!";
flock(D,LOCK_EX);seek(D,0,0);
while () {
my($server,$port) = split(/:/,$_); chomp($port);
my $p = Net::Ping->new();
my $cont = $p->ping($server);
$p->close();
if ($cont)
{ print "$server is alive. \\t ";
#-------//BEGIN FORK//-------#
if ($pid = fork) {
#Здесь запросы с помощью LWP
waitpid($pid,0);
} else {
die "cannot fork: $!" unless defined $pid;
exit;
} #EO if ($pid = fork)
#-------//END FORK//-------#
###############################################
}
else {print "$server NOT reachible!
";}
} #EO while
-
NeoNox:
выведи отладку вместе со временем исполнения
ух. это я не то что бы не умею --- я даже не знаю как это делать. Пока. До сих пор хватало лога...
-
Вот тебе пример функции дебага.
вызываетсяя с любого доступного места как:
debug "I\'m here";
sub debug{
my $now = localtime;
my $data = join(\'\', @_);
my $ra = $ENV{"REMOTE_ADDR"};
my $msg = \'[%l] %s: %m (%d: - %h PID %p)\';
my ($line, $subname) = (caller(1))[2,3];
$msg =~ s/%l/$line/g;
$msg =~ s/%s/$subname/g;
$msg =~ s/%m/$data/g;
$msg =~ s/%d/$now/g;
$msg =~ s/%h/$ra/g;
$msg =~ s/%p/$$/g;
open (FH,">>", "./debug") or die "Can\'t open debug file: $!";
print FH $msg."\\n";
close FH;
}
-
вопрос не праздный. как ограничить рождаемость детей? ;)
(презервативы не предлагать) :)
серьезно - как? хотелось бы чтобы их было не более 5 одновременно.
-
AnnA а подумать с карандашем в руке?
У тебя есть старт процесса и его конец? Вот и записывай +1 при старте процесса и отнимай при завершении.