Как полностью справиться с процессом в Perl CGI под IIS - PullRequest
1 голос
/ 04 апреля 2011

Благодаря некоторым другим замечательным постам здесь (таким как this и that ), у меня есть несколько надежных методов для фонового процесса в скрипте Perl.

Тем не менее, в моей среде (IIS6 на Windows Server 2003), кажется, не совсем фон. Возьми этот скрипт:

use CGI::Pretty qw(:standard);
print header;
print start_html;
print "hi<br>";
system(1,qw(sleep 10));
print "bye";
print end_html;

Браузер будет оставаться «подключенным» в течение 10 секунд, пока выполняется спящий процесс. «Привет» и «пока» будут отображаться на экране, но браузер, похоже, ожидает чего-то большего от сервера (индикаторы выполнения Firefox 4 и IE6 продолжают медленно двигаться в течение этих 10 секунд).

Я бы хотел, чтобы пользователь (для моего реального приложения) поверил, что процесс полностью основан на заднем плане, и был бы полностью в состоянии закрыть веб-страницу. Пока индикатор выполнения все еще движется, я уверен, что они сядут и будут ждать, пока он остановится, прежде чем закрыть или уйти.

Просто чтобы прояснить ситуацию - процесс выглядит фоновым. Я могу закрыть веб-браузер. Реальная задняя работа продолжает выполняться (иногда до часа) без проблем. Я просто хотел бы прояснить это с точки зрения пользовательского интерфейса.

Спасибо!

Ответы [ 2 ]

1 голос
/ 04 апреля 2011

Ваша проблема в том, что программа CGI выполнена, но веб-серверу не было сказано, что она выполнена, и она ждет этого, прежде чем фактически сказать браузеру, что она выполнена.Вам нужно выяснить, как сообщить об этом, или придумать способ взломать эту ошибку.Вот несколько возможных стратегий.

  1. В Unix правильный способ сообщить веб-серверу, что пора уходить, - демонизировать фоновый процесс.Детали того, как это сделать, довольно специфичны для Unix.Однако поиск в Google для Win32 perl daemon привел меня к Win32 :: Daemon , а затем Win32 :: Service , что может помочь вам сделать нечто подобное для Windows.Я видел комментарии без подробностей, предполагающих, что это будет работать.Если вам нужна помощь в выяснении этого, я бы предложил пойти к Perlmonks и спросить там.Здесь больше специфических знаний для Perl, чем здесь.

  2. Предположим, у вас есть какой-то планировщик пакетных заданий для вас.Тогда вместо запуска задания вы можете просто запланировать выполнение задания.Задача подбирается и запускается.Эта стратегия особенно полезна, если задание, которое вам нужно выполнить, достаточно интенсивно, чтобы вы могли запускать его где-нибудь, кроме вашего веб-сервера.

  3. Ваш CGI-скрипт может развернуться и выполнитьHTTP-запрос к веб-серверу для запуска задания, которого он не ждет.Вот краткий пример, показывающий, как это сделать:

    #! /usr/bin/perl -w
    use strict;
    use Carp qw(croak);
    use Data::Dumper qw(Dumper);
    use LWP::UserAgent;
    
    my $ua = LWP::UserAgent->new();
    $ua->add_handler(response_header => sub {croak "complete"}, m_code => 200);
    my $response = $ua->get("http://www.perl.com/");
    
    if ($response->is_success) {
        print "Request backgrounded\n";
    }
    else {
        print "Uh, oh.\n";
    }
    
0 голосов
/ 23 сентября 2011

CGI-скрипты запускаются со стандартным перенаправленным выводом либо напрямую в сокет TCP, либо в канал.Как правило, соединение не закрывается, пока дескриптор и все его копии не будут закрыты.По умолчанию подпроцесс наследует копию дескриптора.

Существует два способа предотвратить ожидание соединения в подпроцессе.Один из них состоит в том, чтобы не допустить наследования дескриптором подпроцесса, другой - чтобы подпроцесс закрывал свою копию дескриптора при запуске.

Если подпроцесс находится в Perl, я думаю, что вы могли бы очень просто закрыть дескриптор:

close(STDOUT);

Если вы хотите запретить подпроцессу наследовать дескриптор, вы можете использовать функцию SetHandleInformation (если у вас есть доступ к Win32 API) или установить bInheritHandles в FALSE при вызове CreateProcess.Или закройте ручку перед запуском подпроцесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...