2008-11-05 2 views
41

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

ответ

50

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

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

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

ignore_user_abort(true); 
set_time_limit(0); 

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

+0

Это гениально. Это также очень хорошо работает с wordpress ajax-вызовом wp_ajax_nopriv_your_trigger. Используйте вышеуказанные два метода в своем крючке и вызовите (возможно, используя планировщик) http://yourdomain.com/wp-admin/admin-ajax.php?action=your_trigger – 2010-12-17 00:49:16

+0

Работали как шарм! Я загружаю файл на свой сервер, а затем я использую скрипт, используя этот метод, чтобы загрузить его на S3, чтобы я мог легко показывать ход загрузки моим пользователям. Я был освежающим, другие просьбы и что не на моем сайте. Вот и вот, файл находится в S3, и мой журнал показывает прогрессию. : D – 2013-03-03 03:03:37

+0

@azure_ardee WordPress уже имеет систему mock cron для выполнения подобных действий. См. Http://codex.wordpress.org/Function_Reference/wp_cron – 2013-11-11 20:50:21

3

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

8

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

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

Я закончил с использованием открытого процесса и процесса, близкие методы, чтобы открыть PHP в режиме CLI следующим образом:

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

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

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

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

26

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

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

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

4

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

например

> #!/usr/bin/php -q 

<?php 

//process logs 

?> 

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

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

2

Подумайте о Gearman

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

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

Offical сайт Gearman

1

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]"; 

?> 
2

В дополнение к 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-подобных системах » есть ошибка/«функция», которая немедленно вызывает libcurl, если значение равно < 1000 мс с ошибкой «ошибка cURL (28): время ожидания было достигнуто». объяснение такого поведения:

[...]

решение отключить сигналы с помощью CURLOPT_NOSIGNAL

плюсы

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

против

  • нужно локон расширение

Ресурсы