Ой, ничего не найдено!

К сожалению, по вашему запросу пока ничего нет (но это только пока!), зато вы можете подписаться на нашу замечательную email-рассылку, чтобы не пропустить самое интересное в будущем.

  • 343

Настройка и отладка расписания (Cron) в Laravel 11 на продакшн-сервере

  • 1 минута на чтение

Настройка и отладка расписания (Cron) в Laravel 11 на продакшн-сервере

Введение

В современных PHP-приложениях часто возникает необходимость выполнять различные задачи по расписанию: обработку очередей, отправку писем, очистку просроченных данных и т.д. Laravel предоставляет удобный способ запуска повторяющихся задач через механизм Task Scheduling. Однако новичкам иногда бывает сложно разобраться, как правильно настроить cron, особенно при работе в Docker-контейнерах или на собственном сервере (Debian, Ubuntu и пр.). В этой статье мы разберём пошагово:

  1. Как работает механизм расписания в Laravel 11.
  2. Как правильно настроить cron-задачу для Laravel (напрямую в системе и внутри Docker).
  3. Как отлаживать ситуацию, когда No scheduled commands are ready to run.
  4. Как убедиться, что задачи действительно выполняются.

Шаг 1. Как работает Laravel Scheduler

  1. Где описываются задачи?
    • В большинстве проектов Laravel задачи прописывают в методе schedule класса App\Console\Kernel.
    • В новых версиях Laravel (включая 11) есть альтернативный способ конфигурации через файл bootstrap/app.php (вместо Kernel), где можно использовать метод ->withSchedule().
  2. Как запускается расписание?
    • Laravel не использует встроенный системный планировщик. Вместо этого вы добавляете задачу (одну!) в системный cron, которая каждую минуту вызывает команду php artisan schedule:run.
    • Когда запускается schedule:run, Laravel проверяет все ваши задачи и смотрит, пора ли их запускать (с учётом указанных интервалов: daily(), hourly(), everyMinute(), и т.д.).
  3. Преимущество такого подхода в том, что вам не нужно прописывать несколько cron-задач в системе. Все задачи (dispatch Jobs, вызовы моделей и т.д.) живут внутри Laravel, а системный cron только «триггерит» их раз в минуту.

Шаг 2. Добавление задачи в расписание

Пример кода (файл bootstrap/app.php):

<?php
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use App\Models\Product;
use Illuminate\Support\Carbon;
use Illuminate\Console\Scheduling\Schedule;
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__ . '/../routes/web.php',
        commands: __DIR__ . '/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        // ...
    })
    ->withExceptions(function (Exceptions $exceptions) {
        // ...
    })
    ->withSchedule(function (Schedule $schedule) {
        // Пример задачи: сбрасываем поле `is_new` у продуктов старше 30 дней
        $schedule->call(function () {
            Product::where('is_new', 1)
                ->where('is_new_set_at', '<=', Carbon::now()->subMonth())
                ->update(['is_new' => 0]);
        })->daily(); // Выполнять задачу ежедневно
    })
    ->create();

В этом примере задача будет выполняться раз в сутки, примерно в полночь.

Шаг 3. Настройка системного cron

3.1. На обычном сервере (Debian/Ubuntu и пр.)

  1. Перейти к пользователю, от имени которого работает веб-сервер (обычно www-data на Debian/Ubuntu) и открыть crontab:
    sudo crontab -u www-data -e
    
  2. Добавить строку, которая раз в минуту будет запускать schedule:run:
    * * * * * cd /path/to/laravel && /usr/bin/php artisan schedule:run >> /dev/null 2>&1
    
    Здесь:
    • * * * * * означает каждую минуту.
    • cd /path/to/laravel — путь к корневой директории вашего проекта.
    • /usr/bin/php artisan schedule:run — команда, которая запускает Laravel Scheduler.
    • >> /dev/null 2>&1 — подавление вывода команд (чтобы не захламлять логи).
  3. Сохранить изменения и проверить, что cron запущен:
    sudo systemctl status cron
    # или
    sudo systemctl restart cron
    
  4. Посмотреть, действительно ли cron срабатывает, можно в логах системы (Debian/Ubuntu):
    grep CRON /var/log/syslog
    
    Если всё верно, вы увидите регулярные записи о запуске.

3.2. В Docker (например, Laravel Sail)

Если ваш Laravel-проект работает внутри контейнера Docker, а не напрямую на хост-системе, нужно учесть нюанс: задача, добавленная в crontab хост-системы, не видит контейнер (или видит с трудом). Поэтому для корректной работы расписания нужно:

  1. Установить cron внутри Docker-контейнера (если его там нет). В случае Laravel Sail cron обычно не установлен по умолчанию.
  2. Добавить нужную строку в crontab контейнера. Проще всего это сделать так:
sail shell
crontab -e

И добавить:

* * * * * /usr/bin/php /var/www/html/artisan schedule:run >> /dev/null 2>&1
  • Путь к php может отличаться, проверьте командой which php в контейнере.
  • Путь к проекту (/var/www/html) может отличаться, смотрите Dockerfile или docker-compose.yml. Далее нужно перезапустить контейнер:
sail restart

и убедиться, что cron внутри контейнера запущен.

Шаг 4. Сообщение «No scheduled commands are ready to run» — это нормально?

При ручном запуске:

sail artisan schedule:run
Специальное предложение: бесплатный хостинг на полгода!
Введите промокод FREE6MONTH при регистрации и наслаждайтесь надежным хостингом бесплатно.

или

php artisan schedule:run

вы можете увидеть сообщение:

INFO  No scheduled commands are ready to run.

Это не ошибка. Дело в том, что Laravel каждый раз проверяет, пора ли запускать ваши задачи. Если вы, например, указали ->daily() (выполнение раз в сутки), а сейчас не полночь, то Scheduler просто сообщает, что "Нет задач, которым пора выполняться". Чтобы протестировать саму логику вашей задачи (убедиться, что код в ->call(...) работает), можно:

  1. Поменять расписание на ->everyMinute(), временно.
  2. Снова вызвать schedule:run.
  3. Убедиться, что задача действительно сработала (посмотреть изменения в базе, логи и т.д.). Таким образом, если у вас в логах нет ошибок, а schedule:run говорит «No scheduled commands are ready to run», скорее всего всё в порядке и задача просто «ждёт» своё время.

Шаг 5. Отладка и проверка

  1. Проверить, что команда действительно прописана Если в проекте версия Laravel поддерживает команду:
    php artisan schedule:list
    
    Вы увидите список всех задач, зарегистрированных в Kernel или в конфигурации через ->withSchedule(). Если вашей задачи нет, убедитесь, что вы не забыли что-то импортировать или сделать return в правильном месте.
  2. Проверить логи
    • Если задача выполняется, но при выполнении возникают ошибки, они часто пишутся в storage/logs/laravel.log.
    • Если логи пусты, обычно это значит, что ошибок нет.
  3. Проверить время на сервере Иногда задачи не срабатывают, если системное время в конфигурации отличается от реального. Убедитесь, что команда:
    date
    
    показывает правильное локальное время. При необходимости проверьте config/app.php:
    'timezone' => 'Europe/Moscow',
    
    или укажите нужный часовой пояс и перезапустите сервис/контейнер.
  4. Убедиться, что код внутри задачи работает Зайдите в Tinker и вручную попробуйте выполнить код:
    sail artisan tinker
    // или
    php artisan tinker
    
    Затем:
    use App\Models\Product;
    use Illuminate\Support\Carbon;
    Product::where('is_new', 1)
        ->where('is_new_set_at', '<=', Carbon::now()->subMonth())
        ->update(['is_new' => 0]);
    
    Если код срабатывает и обновляет нужные записи, значит проблема точно не в самом коде.

Вывод

Настройка крон-задачи для Laravel 11 довольно проста, если понимать общую схему работы schedule:run и убедиться, что системная часть (cron) корректно запускается каждую минуту:

  1. Описать задачи в Laravel (через Kernel или в bootstrap/app.php, как в новых версиях).
  2. Добавить одну cron-запись для php artisan schedule:run.
  3. Следить за логами и не пугаться, если видите сообщение «No scheduled commands are ready to run» — это нормально, когда по текущему расписанию нет задач к запуску. Если же вы используете Docker, то имейте в виду, что в контейнере по умолчанию может не быть cron, и придётся добавить его вручную, а также прописать крон-задачи внутри самого контейнера. Успешного вам планирования задач!

Хостинг, на который можно положиться!
Siteko.net

Устали от медленного хостинга или дорогих тарифов? Тогда вам к нам! Siteko.net — это быстрый и простой хостинг для тех, кто ценит удобство и стабильность.

  • Без падений и нервов — наш uptime почти всегда 100%.
  • Гибкие тарифы — только нужные функции, ничего лишнего.
  • Скорость— сайты грузятся, как пуля!
  • Удобно — разобраться сможет даже новичок, всё под рукой.
  • Поддержка всегда рядом 24/7 поможем решить любой вопрос.

Заходите на Siteko.net и попробуйте нас бесплатно первый месяц! Мы делаем всё, чтобы ваш сайт работал без проблем.

Siteko.net — просто, быстро и надёжно!