У меня есть скрипт PHP, расположенный на /var/www/site/update.php full
, Скрипт запускается автоматически из cron:
/usr/bin/php /var/www/site/update.php full
Но когда я запускаю тот же скрипт с моего сайта:
<?php exec("/usr/bin/php /var/www/site/update.php full") ?>
Он работает около 20 минут, а затем начинает отображать множество сообщений об ошибках. При этом страница перестает загружаться и пишет error 504 Gateway Time-out
на экран.
Я думаю, что curl тоже не поможет. Есть ли другие варианты?
вопрос в том, как запустить, чтобы он мог работать независимо от браузера. код уже существует и разработан. теперь он проходит через крон каждый час. но необходимо запустить его незапланированно, нажав кнопку или ссылку на сайте.
Вы можете изменить set_time_limit(-1);
в сценарии PHP, чтобы предотвратить смерть PHP, но 504 звучит так, как будто у вас запущен nginx, поэтому вам также придется изменить его временные ограничения для этого конкретного ресурса, используя location
узел конфигурации (или основной конфиг ngix) для установки параметров * _timeout
если вам не нужно обновлять вывод каждую секунду, я бы сделал это:
когда кнопка нажата, сохранить флаг «нажата» в каком-то файле
если ($ _ POST [ ‘schedule_script_button’]) {
потрогать (DIR.»/Script_is_scheduled.flag»);
}
используйте cron для запуска скрипта каждую минуту
* * * * * php /var/www/example.com/my-long-script.php
сценарий должен проверить, установлен ли этот флаг, в противном случае прекратить
если (! file_exists (DIR.»/Script_is_scheduled.flag»)) {
выход;
}
// здесь выполняется полная логика скрипта
если флаг установлен, запустите сценарий и сохраните вывод в файл. если вы используете crontab, вы можете использовать echo в скрипте, и crontab следует изменить следующим образом:
* * * * * php /var/www/example.com/my-long-script.php > /var/www/example.com/my-script-output.txt
my-script-output.txt
используя file_get_contents
Функция PHP и просто эхо его содержимого.Я против установки высоких значений ограничения на количество веб-ссылок, которые могут быть использованы злоумышленниками, чтобы отключить ваш сайт, забирая его ресурсы при выполнении длинных сценариев.
То, чего вы пытаетесь достичь, не может быть реализовано в парадигме PHP Web: ваш скрипт выполняется в контексте HTTP-запроса; его выполнение всегда будет прекращено в тот момент, когда ваш посетитель прерывает запрос (закрывает вкладку или браузер, выключает WiFi и т. д.).
Чтобы запустить выполнение длинной фоновой задачи из HTTP-запроса (либо щелчок кнопки, либо программный вызов curl), ваш сервер должен состоять из нескольких компонентов: обычно это очередь сообщений (например, RabbitMQ).
Нажатие кнопки вызовет только сообщение «Задание»: поместите (строковое) сообщение в очередь сообщений, которое описывает тип запуска и параметры (например, сериализованным способом PHP или JSON), а затем сразу же возвращается , Ваш посетитель получает быстрый HTTP-ответ, который гласит: «Ваша работа успешно поставлена в очередь».
Затем, в дополнение к компоненту очереди сообщений, вы должны запустить непрерывно работающий процесс (в PHP CLI с неограниченным временем или демоном на любом языке по вашему выбору). Этот сценарий с бесконечной петлей ставит себя в режим прослушивания (подписчик) по отношению к службе очереди сообщений, и каждый раз, когда приходит сообщение, он выполняет любую необходимую вам длительную обработку.
С состоянием длинной работы ваш посетитель может ознакомиться на специальной странице своих текущих работ, где он также может получить результат для загрузки или просмотра и т. Д. (Пример: различные службы «Преобразование YouTube в Mp3» по всему Интернету)
Это единственный надежный способ обработки длинных фоновых задач, запускаемых онлайн.
Есть несколько альтернатив промежуточному программному обеспечению, которые вы можете использовать для достижения этой цели: RabbitMQ, Redis, Кафка, некоторые примеры, в зависимости от специфики вашей ситуации (в соответствии с такими соображениями, как количество экземпляров демона, необходимость управления приоритетами ожидающих сообщений в очереди или сохранение очереди в случае сбоя и т. д.)
Вы можете найти в RabbitMQ How-To a подробное руководство по PHP.
Я сделал так, как рекомендовано в этой дискуссии PHP выполнить фоновый процесс. страница еще не загружена, но ее результат. это, вероятно, не лучшее решение, но оно работает. Я ожидаю лучшего решения.