Вопрос

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

Это было полезно?

Решение

Ну, вы можете использовать " ignore_user_abort (истина) <> Quot;!

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

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

ignore_user_abort(true); 
set_time_limit(0);

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

Другие советы

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

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

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

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

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

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

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

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

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

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

Это также может помочь: Exec асинхронной оболочки в PHP

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

Подумайте о Gearman

  

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

     

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

Официальный веб-сайт Gearman

В дополнение к ответу бастиандоина вы можете объединить ignore_user_abort(true); с помощью Запрос на скручивание.

Подделать запрос на аборт, установив низкий уровень 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');

Примечание

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

[...]

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

плюсы

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

минусы

  • Нужно наращивать локоны

Ресурсы

Зук.

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

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

?>

Просто вызовите StartBuffer () перед любым выводом и EndBuffer (), когда вы хотите, чтобы клиент закрыл соединение. Код после вызова EndBuffer () будет выполнен на сервере без клиентского подключения.

    private function StartBuffer(){
        @ini_set('zlib.output_compression',0);
        @ini_set('implicit_flush',1);
        @ob_end_clean();
        @set_time_limit(0);
        @ob_implicit_flush(1);
        @ob_start();
    }

    private function EndBuffer(){
        $size = ob_get_length();
        header("Content-Length: $size");
        header('Connection: close');
        ob_flush();ob_implicit_flush(1);
    }

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top