IO v7. Cron скрипты и работа с ними
Описание
Cron (также известный как планировщик задач) - это серверная утилита, которая выполняет команды или задачи (в нашем случае cron-скрипты) в заданное время или через определенные интервалы времени.
Фреймворк позволяет планировать и запускать скрипты, добавляя записи в таблицу cron базы данных проекта в MySQL.
Содержимое файла скрипта
<?php
namespace App\Crons;
use IO\CronTemplate;
class ExampleCron extends CronTemplate
{
public function cron_ask()
{
$this->data_load();
return true;
}
public function cron_do()
{
// логика...
// пример работы с сохраныемыми данными
$this->data['example_variable'] = time();
echo $this->data['example_variable'];
ioFlush();
$this->data_save();
}
}
Файлы cron-скриптов проекта находятся в папке project/src/app/Crons. Имя файла должно начинаться с большой буквы и иметь постфикс Cron.php (пример: ExampleCron.php). Имя класса должно быть таким же, как и название файла, без формата файла .php (пример: ExampleCron).
Функции
cron_ask()
Функция, выполняющаяся перед началом тела скрипта. Обязательная для объявления в классе скрипта.
Обычно здесь только вызывается функция загрузки ранее сохраненных данных data_load() (если это необходимо).
Пример тела функции:
public function cron_ask()
{
$this->data_load();
return true;
}
cron_do()
Основная функция, тело cron скрипта, выполняемая после функции cron_ask(). Обязательная для объявления в классе скрипта.
В конце обычно вызывается функция загрузки ранее сохраненных данных data_save() (если это необходимо).
Пример тела функции:
public function cron_do()
{
// логика...
// пример работы с сохраныемыми данными
$this->data['example_variable'] = time();
echo $this->data['example_variable'];
ioFlush();
$this->data_save();
}
data_load()
Загрузка данных скрипта из таблицы cron_data базы данных проекта в MySQL. Данные загружаются в переменную-массив $this->data.
Обычно прописывается в теле функции cron_ask(), если в скрипте будет использоваться переменная $this->data.
Пример вызова функции:
$this->data_load();
data_save()
Сохранение данных скрипта. Данные записываются в таблицу cron_data базы данных проекта в MySQL для доступности в следующей итерации cron скрипта.
Обычно прописывается в конце тела функции cron_do(), если в скрипте будет использоваться переменная $this->data.
Пример записи данных под ключом example_variable со значением time():
$this->data['example_variable'] = time();
Пример вывода данных под ключом example_variable на экран:
echo $this->data['example_variable'];
Пример вызова функции:
$this->data_save();
Управление запуском
Cron задачи управляются через базу данных проекта в MySQL.
Всего есть 3 таблицы:
cron: управление списком cron-задач.cron_data: данные всех ранее запущенных cron-скриптов (содержимое переменной$this->data).cron_work: лог работы всех ранее запущеных cron-скриптов.
Таблица cron
Здесь содержатся данные всех cron-скриптов проекта.
Структура таблицы:
CREATE TABLE `cron` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`classname` varchar(255) NOT NULL COMMENT 'имя класса скрипта',
`enable` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'запускать ли скрипт (0-нет, 1-да)',
`time_period` int(11) NOT NULL DEFAULT '60' COMMENT 'период запуска скрипта (в секундах)',
`max_threads` int(11) NOT NULL DEFAULT '1' COMMENT 'максимальное количество потоков для запуска скрипта',
`time_work` int(11) NOT NULL DEFAULT '1' COMMENT 'время работы скрипта (в секундах)',
`description` text NOT NULL COMMENT 'описание скрипта',
`last_run` datetime NOT NULL COMMENT 'дата запуска последней итерации (процесса) скрипта',
PRIMARY KEY (`id`),
UNIQUE KEY `classname` (`classname`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='список cron-задач';
Таблица содержит следующие поля:
id: id cron-скрипта (autoincrement).classname: имя класса cron-скрипта (пример:App\Crons\ExampleCron).emable: запускать ли cron-скрипт (0-нет,1-да).time_period: период запуска cron-скрипта в секундах (минимум60).max_threads: максимальное количество потоков для запуска cron-скрипта (не используется, но всегда значение должно быть1).time_work: время работы cron-скрипта (в секундах) (не используется, но всегда значение должно быть1).description: описание cron-скрипта.last_run: дата запуска последней итерации (процесса) cron-скрипта.
Пример SQL-запроса добавления cron-скрипта с названием ExampleCron, который лежит в project/src/app/Crons/ExampleCron.php, который будет запускаться каждые 3 минуты (каждые 180 секунд):
INSERT INTO `cron` (`classname`, `enable`, `time_period`, `description`) VALUES
('App\Crons\ExampleCron', 1, 180, 'скрипт примера cron-задачи');
Таблица cron_data
Здесь содержатся данные всех ранее запущенных cron-скриптов (содержимое переменной $this->data).
Структура таблицы:
CREATE TABLE `cron_data` (
`key` varchar(255) NOT NULL COMMENT 'имя ключа скрипта',
`data` text NOT NULL COMMENT 'значение в формате сериализованного массива',
PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='данные cron-задач';
Таблица содержит следующие поля:
key: имя ключа cron-скрипта (пример:class_App\Crons\ExampleCron).data: значение в формате сериализованного массива с ключами, прописанными в теле cron-скрипта и их значениями.
Таблица cron_work
Здесь содержится лог работы (итераций, процессов) всех ранее запущеных cron-скриптов.
Структура таблицы:
CREATE TABLE `cron_work` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`cron_id` bigint(20) unsigned NOT NULL COMMENT 'id скрипта',
`status` varchar(255) NOT NULL COMMENT 'статус итерации (процесса)',
`time_begin` datetime NOT NULL COMMENT 'дата запуска процесса (итерации)',
`time_end` datetime DEFAULT NULL COMMENT 'дата завершения итерации (процесса)',
`log` longtext NOT NULL COMMENT 'вывод скрипта в процессе его работы (echo и т.п.)',
`timestamps` longtext NOT NULL,
`avg` double NOT NULL DEFAULT '0',
`count` double NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `cron_id` (`cron_id`),
KEY `time_begin` (`time_begin`),
CONSTRAINT `cron_work_ibfk_1` FOREIGN KEY (`cron_id`) REFERENCES `cron` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='лог работы cron-задач';
Таблица содержит следующие поля:
id: id итерации (процесса) (autoincrement).cron_id: id cron-скрипта (cron.id).status: статус итерации (процесса) (DO: выполняется,DONE: завершен).time_begin: дата запуска итерации (процесса).time_end: дата завершения итерации (процесса).log: вывод скрипта в процессе его работы (echo и т.п.).timestamps: ??? (всегда значение равноa:0:{}).avg: ??? (всегда значение равно0).count: ??? (всегда значение равно0).
Принудительный (ручной) запуск
Cron-скрипты можно запускать принудительно вручную.
Обязательное условие - это наличие записи о cron-скрипте в таблице cron базы данных проекта в MySQL, где ему будет присвоен ID, т.к. именно по ID можно запускать тот или иной cron-скрипт.
Запуск происходит путем выполнения команды через терминал сервера в среде, где запущен проект (обычно это docker контейнер проекта проект_cron).
В корне проекта находится файл cron.php, который и запускает cron-скрипты по их ID в таблице cron базы данных проекта в MySQL.
Следующая команда запустит cron-скрипт с ID = 1 (предположим это ExampleCron в таблице cron с ID = 1)
php cron.php 1
Так как в конфигурации docker контейнера компании есть правило, которое требует запускать PHP файлы под определенным пользователем, конечная команда будет выглядеть так:
su wwwdocker -c "php cron.php 1"
Скрипт может быть деактивирован (enable = 0) в таблице cron базы данных проекта в MySQL, но ручной запуск игнорирует это правило.