Perl отправляет ответ ajax, а затем exec () - PullRequest
0 голосов
/ 01 апреля 2012

Сценарий Perl должен получить ajax-запрос, отправить сообщение «success» обратно в браузер, а затем «вызвать» процесс для запуска в фоновом режиме. (этот порожденный процесс может занять 10 минут, поэтому я не хочу, чтобы браузер ждал этого или истекло время ожидания Apache)

У меня сложилось впечатление, что функция Perl exec () сделает это. Лучше, чем использовать fork () или system (), поскольку они должны ждать ответа.

Но, похоже, что скрипт ожидает завершения программы exec (), прежде чем отправить сообщение об успешном завершении в браузер. Вот самый конец моего Perl-скрипта:

print "Content-type: text/html\n\n";
print "success"; # this gets returned via ajax

exec $script_filename, $var1, $var2, $var3; 

Все работает, но браузер не получает сообщение об успехе, пока $ script_filename не завершит работу.

То, что я хочу сделать, похоже на этот предыдущий пост , но там недостаточно подробностей.

Есть идеи? Спасибо.

Ответы [ 2 ]

2 голосов
/ 01 апреля 2012

Apache будет ждать завершения вашего скрипта, прежде чем завершит ответ браузеру.Вы должны запланировать выполнение задания в фоновом режиме, а затем позволить сценарию завершиться.

Чтобы запланировать фоновое задание, вы можете реализовать процессор фоновых задач в качестве демона, который принимает задачи через IPC (например, черезСокет домена UNIX) из сценария perl перед их выполнением.В качестве альтернативы вы можете использовать существующие инструменты UNIX для планирования фоновых заданий, например at или batch.Подробнее см. на этой man-странице .

Если вам требуется очень высокая надежность, вы также можете сохранить задачу во внешнем хранилище, прежде чем подтвердить клиенту, что она запланирована.

0 голосов
/ 02 апреля 2012

Я нашел ответ на другой вопрос StackOverflow, который, похоже, решил мою проблему - см. Ответ Пола Томблина здесь .

Похоже, что если perl-скрипт выполняет exec (), то apache ждет. Но если Perl-скрипт сначала выполняет форк, а затем форк выполняет exec (), тогда все работает как положено.

И вот как это выглядит в моем коде, заменив то, что было в моем исходном посте:

use POSIX 'setsid';

$SIG{CHLD} = 'IGNORE';

# This should flush stdout.
my $ofh = select(STDOUT);$| = 1;select $ofh;

my $kpid = fork;
if ($kpid)
{
    # Parent process
    print "Content-type: text/html\n\n";
    print "success"; # this gets returned via ajax
}
else
{
    close STDIN;
    close STDOUT;
    close STDERR;
    setsid();
    my $gpid = fork;
    if (!$gpid)
    {
        open(STDIN, "</dev/null") ;
        open(STDOUT, ">/dev/null") ;
        open(STDERR, ">/dev/null") ;
        # Child process
        exec($script_filename, $var1, $var2, $var3) ;
    }
    exit 0;
}

Спасибо Адаму за то, что он сразу подтвердил, что то, что я первоначально пытался сделать, было ошибочным.

Спасибо Джонатану за то, что он указал мне правильное направление.

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