Рабочее задание в фоновом режиме от Perl, не ожидая возврата

Правовая оговорка

В первую очередь, я знаю, что этот вопрос (или близкие изменения) задали тысячу раз. Я действительно провел несколько часов, смотря в очевидном и местах not-so-obvious, но может быть что-то маленькое, которое я пропускаю.

Контекст

Позвольте мне определить проблему более ясно: я пишу приложение новостной рассылки, в котором я хочу, чтобы фактический процесс отправки был асинхронен. Как в, пользовательские щелчки "отправляют", возвраты запроса сразу, и затем они могут проверить прогресс определенной страницы (через Ajax, например). Это записано в Вашем традиционном стеке LAMP.

В конкретном хосте я использую, должностное лицо PHP () и система () отключено из соображений безопасности, но системные функции Perl (должностное лицо, система и обратные галочки) не. Таким образом, мое обходное решение состояло в том, чтобы создать "триггерный" сценарий в Perl, который называет фактического отправителя через CLI PHP и перенаправляет к странице прогресса.

Где я застреваю

Очень выравнивают вызовы, которые отправитель на данный момент:

system("php -q sender.php &");

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

Что я уже попробовал

  • Должностное лицо Perl () функция - тот же результат системы ().
  • Изменение команды к: "php-q sender.php | в теперь"), надеясь, что "в" демоне возвратился бы и что сам процесс PHP не будет присоединен к Perl.
  • Выполнение команды 'косвенно': "/bin/sh-c 'php-q sender.php и'" - все еще ожидает, пока sender.php не закончен, отправив.
  • ветвление () 'луг процесс и выполнение системного вызова в ребенке (надо надеяться, отсоединил процесс) - тот же результат как выше

Моя тестовая среда

Только, чтобы быть уверенным, что я не пропускаю ничего очевидного, я создал sleeper.php сценарий, который просто спит за пять секунд до выхода. И test.cgi сценарий, который похож на это, дословно:

#!/usr/local/bin/perl
system("php sleeper.php &");
print "Content-type: text/html\n\ndone";

Что я должен попробовать теперь?

9
задан Rafael Almeida 15 April 2010 в 16:41
поделиться

5 ответов

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

Это легко сделать с помощью модуля CPAN Proc :: Daemon :

use Proc::Daemon;
# do everything you need to do before forking the child...

# make into daemon; closes all open fds
Proc::Daemon::Init();
9
ответ дан 4 December 2019 в 09:12
поделиться

Другой вариант - настроить сервер gearman и рабочий процесс (или процессы), которые отправляют электронную почту. Таким образом, вы контролируете, сколько электронных писем происходит одновременно, и никакого разветвления не требуется. Клиент (ваша программа) может добавить задачу на сервер gearman (в фоновом режиме, не дожидаясь результата при желании), и задания ставятся в очередь до тех пор, пока сервер не передаст задание доступному исполнителю. Для gearman есть API-интерфейсы perl и php, так что это очень удобно.

1
ответ дан 4 December 2019 в 09:12
поделиться

Проблему удалось решить.По-видимому, то, что удерживало его от возврата, было то, что вызов отправителя таким образом не отключал стандартный вывод. Итак, решением было просто изменить системный вызов на:

system("php sender.php > /dev/null &");

Спасибо всем за помощь. Фактически, когда я читал всю историю о «демонизации» процесса, мне пришла в голову идея отключить stdout.

0
ответ дан 4 December 2019 в 09:12
поделиться

Используйте fork () , а затем вызовите систему в дочернем процессе.

my $pid = fork();
if (defined $pid && $pid == 0) {
    # child
    system($command);    # or exec($command)
    exit 0;
}
# parent
# ... continue ...
6
ответ дан 4 December 2019 в 09:12
поделиться

Иногда STDERR и STDOUT также могут блокировать систему... Чтобы получить и то, и другое, я использую (для большинства сред оболочки (bash, csh и т.д.), которые я использую...):

system("php sender.php > /dev/null 2>&1 &");
7
ответ дан 4 December 2019 в 09:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: