Все таки на PHP писать скрипты, которые должны выполняться часами, не самая лучшая идея.
Каждую большую задачу можно разбить на маленькие.
Допустим, вам надо скачать информацию по всем товарам магазина.
Информация находится по адресу
https://api.site.ru/item/N, где N - ID товара от 1 до 1М.
1. Сделаем таблицу задач со следующей структурой:
- task_id
- item_url (например,
https://api.site.ru/item/1)
- status (0 - задача не обработана, 1 - задача в работе, 2 - задача завершена)
- process_id (ID PHP процесса который занял задачу для выполнения)
2. Напишем простой скрипт, который будет брать из таблицы задач одну задачу, скачивать информацию по товару, сохранять ее и завершаться. Тут самое сложное, сделать так, чтобы два параллельных запуска этого скрипта не взялись выполнять одну и туже задачу. Для этого можно сделать что-то типа
$process_id = microtime(TRUE).getmypid(); // некоторое уникальное значение
// попытка занять свободную задачу на выполнение
$mysqli->query("UPDATE `task` SET `process_id` = $process_id WHERE `status` = 0 AND `process_id` = 0");
// получаем информацию по задаче
$mysqli->query("SELECT * FROM `task` WHERE `process_id` = $process_id");
// выполняем задачу, что-то скачиваем
...
// ставим в таблице задаче статус "завершена"
3. Теперь надо только организовать постоянный запуск этого скрипта.
Создадим sh скрипт, например, task.sh и поставим в кроне его запуск на каждую минуту.
Сам же скрипт будет каждую секунду вызывать task.php.
#!/bin/bash
for i in $(seq 0 59)
do
if [ `ps aux | grep -c task.php` -le 10 ]; then
/usr/bin/wget -q -O /dev/null http://localhost/task.php &
fi
sleep 1;
done
Заключение. Таким образом вы сможете контролировать ход выполнения глобальной задачи, смотреть какие микрозадачи подвисли и отправлять их на перезапуск. Предложенное решение можно сильно улучшить.