Фоновые процессы PHP - PullRequest
       40

Фоновые процессы PHP

41 голосов
/ 05 ноября 2008

Я пытаюсь сделать сценарий PHP, у меня есть сценарий завершен, но это занимает около 10 минут, чтобы завершить процесс, для которого он предназначен. Это не проблема, однако я полагаю, что все это время я должен держать страницу загруженной, что раздражает. Могу ли я получить его, чтобы я запустил процесс, а затем вернулся через 10 минут и просто просмотрел сгенерированный файл журнала?

Ответы [ 11 ]

50 голосов
/ 05 ноября 2008

Ну, вы можете использовать " ignore_user_abort (true)"

Таким образом, скрипт продолжит работать (следите за продолжительностью скрипта, возможно, добавьте « set_time_limit (0)»)

Но предупреждение здесь: вы не сможете остановить скрипт с этими двумя строками:

ignore_user_abort(true); 
set_time_limit(0);

За исключением того, что вы можете получить прямой доступ к серверу и завершить процесс там! (Был там, сделал бесконечный цикл, снова и снова вызывая себя, заставил сервер резко заскрипеть, кричал на ...)

26 голосов
/ 05 ноября 2008

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

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

Преимущество здесь в том, что вы не блокируете поток apache в течение 10 минут.

8 голосов
/ 05 ноября 2008

У меня было много проблем с такого рода процессами под Windows; Моя ситуация немного отличалась тем, что меня не волновал ответ «сценария» - я хотел, чтобы сценарий запускался и позволял проходить другим запросам страницы, пока он был занят работой.

По какой-то причине; У меня были проблемы с ним: либо зависание других запросов, либо истечение времени ожидания примерно через 60 секунд (для apache и php было установлено время ожидания примерно через 20 минут); Также оказывается, что Firefox отключается через 5 минут (по умолчанию), так что после этого вы не сможете узнать, что происходит через браузер, не изменив настройки в Firefox.

В итоге я использовал методы open и process close для открытия php в режиме cli, например:

pclose(popen("start php myscript.php", "r"));

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

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

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

6 голосов
/ 05 ноября 2008

Это может быть полезно, также: Асинхронная оболочка в PHP

5 голосов
/ 05 ноября 2008

Я думаю, что команда shell_exec - это то, что вы ищете.

Однако в безопасном режиме он отключается.

Статья об PHP-руководстве об этом находится здесь: http://php.net/shell_exec

Здесь есть статья об этом: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/

4 голосов
/ 06 ноября 2008

Есть еще одна опция, которую вы можете использовать, запустить скрипт CLI ... Он будет работать в фоновом режиме, и вы даже можете запустить его как cronjob, если хотите.

например,

> #!/usr/bin/php -q

<?php

//process logs

?>

Это может быть настроено как cronjob и будет выполняться без ограничения по времени .... хотя этот пример для операционной системы на основе Unix.

FYI У меня есть скрипт php, работающий с бесконечным циклом, который выполняет некоторую обработку и работает последние 3 месяца без остановки.

3 голосов
/ 05 ноября 2008

Вы можете использовать ignore_user_abort() - таким образом, скрипт продолжит работу, даже если вы закроете браузер или перейдете на другую страницу.

2 голосов
/ 21 февраля 2015

В дополнение к ответу bastiandoeen вы можете объединить ignore_user_abort(true); с запросом cUrl .

Подделать запрос на прерывание установки, установив низкий уровень CURLOPT_TIMEOUT_MS и продолжить обработку после закрытия соединения:

function async_curl($background_process=''){

    //-------------get curl contents----------------

    $ch = curl_init($background_process);
    curl_setopt_array($ch, array(
        CURLOPT_HEADER => 0,
        CURLOPT_RETURNTRANSFER =>true,
        CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms
        CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute
        CURLOPT_VERBOSE => 1,
        CURLOPT_HEADER => 1
    ));
    $out = curl_exec($ch);

    //-------------parse curl contents----------------

    //$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    //$header = substr($out, 0, $header_size);
    //$body = substr($out, $header_size);

    curl_close($ch);

    return true;
}

async_curl('http://example.com/background_process_1.php');

NB

Если вы хотите, чтобы cURL превысил время ожидания менее чем за одну секунду, вы можете использовать CURLOPT_TIMEOUT_MS, хотя есть ошибка / «функция» в «Unix-подобном» systems ", что приводит к немедленному истечению времени ожидания libcurl, если значение < 1000 мс с ошибкой «Ошибка cURL (28): истекло время ожидания». объяснение этого поведения:

[...]

Решение состоит в том, чтобы отключить сигналы с помощью CURLOPT_NOSIGNAL

профи

  • Нет необходимости переключать методы (Совместимые окна и Linux)
  • Нет необходимости реализовывать обработку соединения через заголовки и буфер (независимо от версии браузера и PHP)

против

  • Нужно удлинить локон

Ресурсы

2 голосов
/ 25 июня 2013

Подумайте о Gearman

Gearman - это универсальная прикладная среда для работы над несколько машин или процессов. Это позволяет приложениям завершать параллельные задачи, обработка баланса нагрузки и вызов функций между языками. Каркас может быть использован в различных приложений, от веб-сайтов высокой доступности до транспорта События репликации базы данных.

Это расширение предоставляет классы для написания клиентов Gearman и работников. - Исходное руководство php

Официальный сайт Gearman

1 голос
/ 11 января 2014

Zuk.

Я почти уверен, что это сработает:

<?php 

pclose(popen('php /path/to/file/server.php &'));
echo "Server started. [OK]"; 

?>

Важно &. Он говорит оболочке не ждать завершения процесса.

Также Вы можете использовать этот код в своем php (как сказал "bastiandoeen")

ignore_user_abort(true); 
set_time_limit(0);

в команде остановки сервера:

<?php

$output;
exec('ps aux | grep -ie /path/to/file/server.php | awk \'{print $2}\' | xargs kill -9 ', $output);
    echo "Server stopped. [OK]";

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