fork. CGI-скрипт ждет выполнения проги.

Elina74

Есть у меня сервер. На нем лежат: перловый скрипт и скомпилированная прога. Работает апач.
Я из скрипта запускаю прогу. Прога что-то долго делает. Я не хочу ждать того момента, пока она закончит работу, поэтому делаю fork и запускаю прогу с помощью exec. Другая часть скрипта, которая продолжает работать после разветвления, пишет на экран сообщение типа "подождите пожалуйста". До этого момента у меня уже все написано и работает.
Хотелось бы чтобы после этого скрипт автоматически перегружался и проверял, выполнилась ли до конца прога или нет. Для этого можно пользоваться тем, что прога в конце своей работы создает маленький текстовый файлик. Если прога не закончила работать, писать на экран какую-нибудь постоянно обновляющуюся информацию, например текущее время или номер попытки.
Я пока не в курсе, как вышеописанное называется, поэтому и спрашиваю о терминологии.
Если вас не затруднит, опишите хотя бы в общих словах, как лучше такой скрипт написать. Или дайте ключевые слова. Или рабочий скрипт.

kruzer25

AJAX?
Хотя, если нет цели сделать всё уж очень красиво - можно обойтись и очень простым способом - из скрипта с надписью "подождите" перекидывать через секунду на yourScript.pl?checkstatus, а в checkstatus ничего не запускать, только проверять, выполнили ли программу; если выполнили - выдавать результта, если нет - говорить "подождите" и через секунду опять перекидывать.
Соответственно, с ajax - то же самое, только ничего никто перезагружать не будет, а браузер каждую секунду будет сам обращаться к checkstatus, не перезагружая при этом страницу; и, если есть результат - выводить его.

Elina74

перекидывать через секунду на yourScript.pl?checkstatus
с помощью
<META HTTP-EQUIV="Refresh" content="1;URL=yourScript.pl?checkstatus">
?
или как-то еще?

pilot

Либо так, либо AJAX, суть одна. Разница только в клиенте — в js и html.

pitrik2

или как-то еще?
ну еще джаваскрипт таймер можно поставить

Elina74

Наверное я чего-то не понимаю в форках и сделал не так.
Этот код после запуска mainprog3.pl тормозит секунд пять и выдает результат tick=2, а я хотел бы, чтобы он каждую секунду обновлял страницу.
Если же закомментить все кроме редиректа в первом условии и
if($tick == 0){
print $q->redirect('mainprog3.pl?tick=1');
}
и заменить строчки
if(!fileready{
# if($tick<5){
на
# if(!fileready{
if($tick<5){
то скрипт отлично обновляется каждую секунду и через пять секунд выдает результат $tick=5 и все хорошо.
------------------------------------------------------
mainprog3.pl

#!/usr/bin/perl -w
use strict;
use CGI;
my $q = new CGI;
my $tick = $q->param('tick');
if(!defined $tick){$tick = 0}
my $pid;

if($tick == 0){
if(!defined ($pid = fork{
die "can't fork $!";
}
elsif($pid){
#parent
print $q->redirect('mainprog3.pl?tick=1');
}
else{
#child
exec ("/usr/bin/perl", "./otherprog.pl") || die $!;
}
}
else{
$tick++;
print "Content-type: text/html\n\n";
print "<html>\n<head>\n";
if(!fileready{
# if($tick<5){
print "<META HTTP-EQUIV=\"Refresh\" content=\"1;URL=mainprog3.pl?tick=$tick\">\n";
}
else{
print "finihed<br>\n";
print "<a href=\"mainprog3.pl\">again</a><br>\n"
}
print "current tick = $tick\n";
print "</head>\n</html>\n";
}
sub fileready{
my $path = "/home/cosrad/users/m_users/";
my $flag = 0;
if(-e $path."result.txt"){
$flag = 1;
}
return($flag);
}

otherprog.pl

#!/usr/bin/perl -w
$sum = 0;
$path = "/home/cosrad/users/m_users/";

unlink($path."result.txt");

for($i=0; $i<10000000; $i++){
$sum += $i;
}

open OUT, ">".$path."result.txt" || die $!;
flock OUT, 2;
print OUT "other sum=", $sum, "\n";
close OUT;

Elina74

Вот что мне написал про это друг по имени rumith:
-------------------------
Ajax тут совершенно не нужен; очнитесь, люди!
Есть в никсах отличный вызов wait. Ман, к примеру, тут:
http://linux.about.com/od/commands/l/blcmdl2_wait.htm
Соотв., в перле или что ты там юзаешь, есть интерфейс к ней, который
тебе и нужно использовать. Не нужны никакие таймеры или файлы - сразу по завершении программы тебе возвращается управление.
Итак:
1) юзер кликает на кнопку, javascript-ом пишешь ему Please Wait.... и
отсылаешь запрос
2) форкаешь скрипт, исполняешь дитём твою прогу, папе говоришь wait и
после неё пишешь обработку результатов работы проги и возврат http response.

Marinavo_0507

Это нормально, если прога работает не более секунд 30.
Иначе будут проблемы.

Elina74

Во, я тоже так думаю, она может при некоторых входных данных работать минут по десять.

vbgt99912

Во, я тоже так думаю, она может при некоторых входных данных работать минут по десять.
Зависит от задачи. Я примерно в таком случае открыл демоном TCP-порт (локально с которым общается скрипт. Но там была работа демона, которую никто вызывает. То есть там это точно необходимо. А здесь - ХЗ.
Кстати, у меня демон тоже на perl, работы у него не много - (Daemon::Generic)

Marinavo_0507

Ещё и какой-то пул задач придётся делать, значит. Иначе тебе пицот штук таких запустят в фоне.

Elina74

Только что потестил. Через десять минут этот скрипт выдает ошибку 500 и предлагает сохранить пустой pl файл. Если работа идет менее десяти минут, выдает ответ.

#!/usr/bin/perl -w
use strict;
#use Time::local;
my $pid;
my $path = "/home/cosrad/users/m_users/";
if(!defined ($pid=fork{
print "I can't fork\n";
exit(0);
}
elsif($pid){
print "Content-type: text/html\n\n";
print "I'm parent<br>\n";
print "start time: ", localtime . "<br>\n";
wait;
print "Parent finished waiting<br>\n";
open(IN, $path . "result.txt");
print <IN>, "<br>\n";
print "end time: ", localtime . "<br>\n";
}
else{
exec("/usr/bin/perl","./otherprog.pl");
}

kruzer25

Видимо, на сервере настроено, что нельзя скрипты исполнять больше 10 минут.
А если бы ты в ИЕ это смотрел - тебе бы через 30 секунд сказали "не удаётся отобразить страницу".
Это жутко неправильный подход, который опирается на то, что клиент будет столько времни ждать, что сервер разрешит столько времени выполнять скрипт, и что соединение вдруг за эти 10 минут не порвётся.
AJAX тут действительно ни при чём, можно просто страницу обновлять, как я сказал выше. AJAX - это только для красоты (не очень приятно, когда каждую секунду страница перерисовывается, дёргается прогрессбар и раздаётся характерный щелчок).

Andbar

А если бы ты в ИЕ это смотрел - тебе бы через 30 секунд сказали "не удаётся отобразить страницу".
юзай https, будет тебе счастье в виде >30сек на ожидание

kruzer25

юзай https, будет тебе счастье в виде >30сек на ожидание
От возможности сделать таймаут >30 секунд такой способ становится лучше и правильнее?
Оставить комментарий
Имя или ник:
Комментарий: