← Назад к вопросам

Как запускать PHP скрипт каждые 20 секунд?

2.2 Middle🔥 162 комментариев
#PHP Core#Инфраструктура и DevOps

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Обработка периодических задач в PHP

Для выполнения PHP скрипта с интервалом 20 секунд существует несколько подходов, выбор которых зависит от контекста и требований.

Основные подходы

1. Cron-задания (для Linux/Unix систем)

Cron — классическое решение для периодических задач, но минимальный интервал — 1 минута. Для 20 секунд потребуется комбинированный подход:

# В crontab -e добавляем 3 строки с разными смещениями
* * * * * /usr/bin/php /путь/к/скрипту.php
* * * * * sleep 20; /usr/bin/php /путь/к/скрипту.php
* * * * * sleep 40; /usr/bin/php /путь/к/скрипту.php

Недостатки: Не точные 20 секунд (зависит от времени выполнения скрипта), сложность управления.

2. Демоны на PHP

Создание демона, который работает постоянно и выполняет задачи по таймеру:

<?php
declare(ticks=1);

// Демонизация процесса
$pid = pcntl_fork();
if ($pid < 0) exit("Ошибка fork");
if ($pid > 0) exit; // Родительский процесс завершается

// Создаем новую сессию
posix_setsid();

// Основной цикл демона
while (true) {
    // Ваша логика выполнения
    processTask();
    
    // Ожидание 20 секунд
    sleep(20);
}

function processTask() {
    // Основная логика скрипта
    file_put_contents('log.txt', date('Y-m-d H:i:s') . PHP_EOL, FILE_APPEND);
}

Преимущества: Точный контроль интервалов. Недостатки: Требует управления процессами, может быть сложно в отладке.

3. Использование системного планировщика

Для Systemd (современные Linux-системы):
# /etc/systemd/system/my-task.service
[Unit]
Description=My PHP Task

[Service]
Type=simple
ExecStart=/usr/bin/php /путь/к/демону.php
Restart=always

[Install]
WantedBy=multi-user.target
# /etc/systemd/system/my-task.timer
[Unit]
Description=Timer for My PHP Task

[Timer]
OnBootSec=1min
OnUnitActiveSec=20s
AccuracySec=1s

[Install]
WantedBy=timers.target
Для Supervisor (управление процессами):
[program:php-task]
command=/usr/bin/php /путь/к/скрипту.php
process_name=%(program_name)s_%(process_num)02d
numprocs=1
autostart=true
autorestart=true
startsecs=0
stopwaitsecs=20

4. Очереди сообщений и воркеры

Современный подход с использованием брокеров сообщений:

<?php
// Пример с использованием Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

// Воркер, проверяющий очередь каждые 20 секунд
while (true) {
    $task = $redis->rpop('task_queue');
    
    if ($task) {
        processTask($task);
    } else {
        // Если очередь пуста, ждем 20 секунд
        sleep(20);
        // Альтернативно: добавляем периодическую задачу
        addScheduledTask();
    }
}

function addScheduledTask() {
    // Логика добавления задачи
}

5. Swoole или ReactPHP (асинхронные фреймворки)

<?php
// Пример с Swoole Timer
swoole_timer_tick(20000, function () {
    // Этот коллбэк будет выполняться каждые 20000 мс (20 секунд)
    processTask();
});

// Или с ReactPHP
$loop = React\EventLoop\Factory::create();

$loop->addPeriodicTimer(20, function () {
    processTask();
});

$loop->run();

Рекомендации по выбору подхода

Для веб-приложений:

  • Очереди задач (RabbitMQ, Redis, Beanstalkd) с воркерами
  • Планировщики фреймворков (Laravel Scheduler, Symfony Messenger)

Для системных задач:

  • Systemd Timer для точного планирования
  • Supervisor для управления демонами

Для высоконагруженных систем:

  • Асинхронные решения (Swoole, ReactPHP)
  • Kubernetes CronJobs в контейнеризированных средах

Критические аспекты реализации

  1. Блокировка и конкуренция: Используйте файловые блокировки или мьютексы:
$fp = fopen('/tmp/lockfile', 'w');
if (flock($fp, LOCK_EX | LOCK_NB)) {
    processTask();
    flock($fp, LOCK_UN);
}
fclose($fp);
  1. Мониторинг и логирование:
function processTask() {
    $startTime = microtime(true);
    
    try {
        // Основная логика
    } catch (Exception $e) {
        logError($e->getMessage());
    }
    
    $duration = microtime(true) - $startTime;
    if ($duration > 15) {
        logWarning("Выполнение заняло {$duration} секунд");
    }
}
  1. Обработка ошибок и перезапуск:
$maxFailures = 3;
$failureCount = 0;

while (true) {
    try {
        processTask();
        $failureCount = 0; // Сброс счетчика при успехе
    } catch (Exception $e) {
        $failureCount++;
        if ($failureCount >= $maxFailures) {
            exit("Критическая ошибка после {$maxFailures} попыток");
        }
    }
    
    sleep(20);
}

Выводы

Для точного выполнения каждые 20 секунд рекомендуется:

  1. Systemd Timer для системных задач Linux
  2. Демон на PHP с Supervisor для гибкого управления
  3. Очереди задач для веб-приложений
  4. Swoole Timer для высокопроизводительных асинхронных систем

Важно: Любое решение должно включать мониторинг, логирование и обработку ошибок, так как частые запуски увеличивают вероятность сбоев и конкуренции за ресурсы.

Как запускать PHP скрипт каждые 20 секунд? | PrepBro