Запрос на запуск фонового php скрипта

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

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

Есть ли способ добиться этого? Я работаю с php7.0 и сервером apache2 (у меня нет прямого доступа к конфигурации сервера apache, поэтому, если это возможно, я ищу вариант на стороне клиента)

В идеале это можно сделать с помощью бэкэнда очереди / рабочего. Но для этого требуется, чтобы вы могли настраивать постоянные фоновые задачи на сервере. Не похоже, что это возможно. Возникает вопрос, какие именно возможности делать и не у вас есть?

deceze 06.07.2018 12:06

У меня есть доступ к файлам на сервере, к модификациям crontab и к серверу MySQL. По поводу чего-нибудь еще я могу попросить мою поддержку в выполнении этой работы (но они не всегда очень готовы к сотрудничеству ...). Спрошу очередь / рабочих

JM445 06.07.2018 12:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
2
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

вы можете создать скрипт php для выполнения скрипта оболочки bash или использовать для этого метод exec()

Да, но сценарий убивается, когда умирает сценарий php, не так ли?

JM445 06.07.2018 13:45

много вещей, чтобы справиться с этим, вы можете использовать какую-либо службу для проверки процесса, например Monit, или вы даже можете заставить службу cron выполнить процесс снова

Evinn 09.07.2018 05:53
Ответ принят как подходящий

Если кто-то еще ищет способ добиться этого, вот решение, которое я нашел:

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

Затем в Ajax я вызываю другой сценарий, чтобы получить эволюцию рабочего, и, наконец, я получаю результат и убиваю дочерний процесс, когда все будет сделано.

Вот код моего рабочего класса:

class AsyncWorker
{
    private $pid;
    private $worker;

    private $wMgr;

    public function __construct($action, $content, $params = NULL)
    {
        $this->wMgr   = new WorkersManager();
        $pid = pcntl_fork(); // Process Fork
        if ($pid < 0) {
            Ajax::Response(AJX_ERR, "Impossible de fork le processus");
        } else if ($pid == 0) { // In the child, we start the job and save the worker properties
            sleep(1);
            $this->pid    = getmypid();
            $this->worker = $this->wMgr->fetchBy(array("pid" => $this->pid));
            if (!$this->worker) {
                $this->worker = $this->wMgr->getEmptyObject();
                $this->wMgr->create($this->worker);
            }
            $this->worker->setPid($this->pid);
            $this->worker->setAction($action);
            $this->worker->setContent($content);
            $this->worker->setPercent(0.00);
            $this->worker->setResult("");
            $this->wMgr->update($this->worker);
            $this->launch($params);
        } else { // In the father, we save the pid to DB and answer the request.
            $this->worker = $this->wMgr->fetchBy(array("pid" => $this->pid));
            if (!$this->worker) {
                $this->worker = $this->wMgr->getEmptyObject();
                $this->worker->setPid($pid);
                $this->wMgr->create($this->worker);
            }
            Ajax::Response(AJX_OK, "Worker started", $this->worker->getId());
        }
    }

    // Worker job
    private function launch($params = NULL)
    {
        global $form, $_PHPPATH, $url, $session;
        session_write_close(); // This is useful to let the user make new requests
        ob_start(); // Avoid writing anything

        /*
        ** Some stuff specific to my app (include the worker files, etc..)
        */            

        $result = ob_get_contents(); // Get the wrote things and save them to DB as result
        $this->worker->setResult($result);
        $this->worker->setPercent(100);
        ob_end_clean();
    }
}

Это немного сложно, но у меня не было выбора, так как у меня нет доступа к серверным плагинам и библиотекам.

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