Как выполнить большой PHP Script? - PullRequest
18 голосов
/ 15 мая 2010

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

Что я действительно хочу сделать, так это отправлять SMS своим пользователям, используя сторонний API. Таким образом, я в основном предоставляю свой сценарий с массивом телефонных номеров и запускаю метод отправки SMS.

Однако при условии, что отправка 1 SMS займет 5 секунд, и я хочу отправить 1000 SMS, что составляет примерно 1-2 часа. Я не могу использовать set_time_limit(), потому что я на общем хосте.

Один из способов сделать это - сохранить номера в сеансе, выполнить каждое SMS и использовать javascript для обновления этой страницы до конца. Таким образом, мне нужно держать браузер открытым, и выполнение будет остановлено, если подключение к Интернету будет отключено.

Итак, есть ли лучший способ сделать это?

Надеюсь, я достаточно ясен, чтобы объяснить, чего я хочу? Я хочу выполнить большой скрипт, выполнение которого может занять несколько часов без истечения времени ожидания.

Ответы [ 7 ]

21 голосов
/ 15 мая 2010

PHP-сценарий, выполняемый из командной строки или из сценария оболочки, задания cron и т. Д., Не имеет тайм-аута.

Для сценариев, вызываемых CLI, даже если вы динамически устанавливаете время ожидания сценария PHP с помощью функции set_time_limit(), это не имеет никакого эффекта.

5 голосов
/ 15 мая 2010

Если ваш хост позволяет, задания cron являются лучшим решением. Задание cron - это обычный php-скрипт, который автоматически запускается веб-сервером через определенный промежуток времени. Для ваших нужд я бы создал скрипт, который будет запускаться каждые 5 минут и обрабатывать ваши числа партиями по 100 (очевидно, вы захотите настроить временной интервал и размер партии в соответствии с требованиями). Это снизит нагрузку на ваш сервер и предотвратит проблемы с вашим хостинг-провайдером из-за перегрузки ресурсов.

Чтобы отслеживать, какой пакет должен обрабатывать ваш скрипт, я бы настроил таблицу track_batch. Эти столбцы должны дать вам хорошее представление о том, как решить проблему:

id, date_run, start_record, end_record, final_run

По существу:

  • Проверьте, чтобы увидеть дату последнего пакетный запуск. Если это не текущая дата (или любой другой идентификатор, который вы выберете для использовать) для текущей партии, затем продолжить.
  • Если последний запуск серии был для текущей даты, то проверьте столбец final_run, чтобы увидеть, вы уже закончили обработку все цифры.
  • Если у вас еще есть числа для обработки, используйте начало и конец записи в сочетании с MySQL LIMIT, чтобы построить запрос БД, который ваш скрипт будет использовать для получения следующего партия.
  • Обработайте ваши номера.
  • Сохраните всю информацию из этого пакета в таблице track_batch.
  • Если количество возвращаемых запросом всегда меньше максимального размер партии, вы достигли конца и может установить столбец final_run в 1.

Как только вы получите свой скрипт, вам нужно будет настроить саму задачу cron. Общие хосты, скорее всего, будут иметь свои собственные пользовательские интерфейсы для этого, поэтому они, вероятно, являются лучшими людьми, которые спросят, как только ваш скрипт заработает.

5 голосов
/ 15 мая 2010

PHP-скрипты, запускаемые из командной строки, не затрагиваются опцией max_execution_time.
Так что вам совсем не о чем беспокоиться.

3 голосов
/ 15 мая 2010

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

Вместо этого, если вы рассчитываете, что каждое SMS займет 5 секунд, используйте этот подход:

while( $there_are_more_sms_to_be_sent ){
  set_time_limit(30); // enough spare time, just in case.

  // Do your sending, blah blah
}

Таким образом, ограничение по времени будет последовательно обновляться до 30 секунд. Конечно, у вас может быть проблема бесконечного цикла с этим единственным while, но если у вас есть другие вызовы внутри этого while, этот предел предотвратит эти вызовы, чтобы быть виноватыми.

0 голосов
/ 15 мая 2010

В случае, если вы можете запустить CRON JOBS

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

У меня есть что-то вроде:

<?php
// PSEUDO CODE
// grab pending from queue

// <for> {
// update to running
exec("/usr/bin/php /path/to/send.php {$id} > /dev/null &");
// }

и send.php отправит каждое смс. Прямо сейчас у меня это работает со скоростью 300 в минуту, так как это максимальная частота, которую вы можете настроить для задания cron

0 голосов
/ 15 мая 2010

Альтернативой использованию JavaScript является добавление мета-тега Refresh на свою страницу:

<meta http-equiv="Refresh" content="2; url=http://yoururl/script.php&step=x" ?>

Два в content="2; url=.. указывает браузеру загружать URL через 2 секунды после загрузки страницы.

0 голосов
/ 15 мая 2010

Вы можете или вы не можете использовать set_time_limit()?

Если вы можете .. Используйте это:

<?php
// Runs forever and ever...
set_time_limit(-1);
?>
...