Может войдёшь?
Черновики Написать статью Профиль

Планировщик задач

перевод документация 5.х

  1. 1. Введение
    1. 1.1. Запуск планировщика
  2. 2. Определение планировщика
    1. 2.1. Настройки частоты планировщика
    2. 2.2. Предотвращение перекрытий задач
    3. 2.3. Режим обслуживания
  3. 3. Выходные данные задачи
  4. 4. Обработчики прерываний задач
Этот перевод актуален для англоязычной документации на (ветка 5.3) , (ветка 5.2) и (ветка 5.1). Опечатка? Выдели и нажми Ctrl+Enter.

Введение

Раньше вы могли создавать Cron-записи для каждой запланированной задачи на вашем сервере. Но это могло быстро превратиться в рутину, так как планировщик задач больше не находится в системе контроля версий, и вы должны заходить через SSH на свой сервер, чтобы добавить Cron-записи.

Планировщик команд Laravel позволяет вам гибко и выразительно определить планирование своих команд в самом Laravel. И для этого на вашем сервере необходима только одна Cron-запись. Ваш планировщик задач определён в методе PHPschedule() файла app/Console/Kernel.php. Чтобы помочь вам начать, там уже есть простой пример с методом.

Запуск планировщика

При использовании планировщика вам надо добавить на ваш сервер только одну эту Cron-запись. Если вы не знаете, как добавлять Cron-записи на сервер, то можете использовать такой сервис, как Laravel Forge, который может управлять Cron-записями для вас:

sh* * * * * php /path/to/artisan schedule:run >>/dev/null 2>&1

Этот Cron будет вызывать планировщик команд Laravel каждую минуту. Когда будет выполнена команда shschedule:run, Laravel обработает ваши запланированные задачи и запустит только те задачи, которые должен.

Определение планировщика

Вы можете определить все свои запланированные задачи в методе PHPschedule() класса App\Console\Kernel. Для начала давайте посмотрим на пример планирования задачи. В этом примере мы запланируем замыкание PHPClosure, которое будет вызываться каждый день в полночь. В PHPClosure мы выполним запрос БД, чтобы очистить таблицу:

PHP
<?php

namespace App\Console;

use 
DB;
use 
Illuminate\Console\Scheduling\Schedule;
use 
Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class 
Kernel extends ConsoleKernel
{
  
/**
   * Artisan-команды вашего приложения.
   *
   * @var array
   */
  
protected $commands = [
    \
App\Console\Commands\Inspire::class,
  ];

  
/**
   * Определяем планировщик команд приложения.
   *
   * @param \Illuminate\Console\Scheduling\Schedule $schedule
   * @return void
   */
  
protected function schedule(Schedule $schedule)
  {
    
$schedule->call(function () {
      
DB::table('recent_users')->delete();
    })->
daily();
  }
}

В дополнение к планированию вызовов PHPClosure вы можете также запланировать Artisan-команды и команды операционной системы. Например, вы можете использовать метод PHPcommand(), чтобы запланировать Artisan-команду, используя либо имя команды, либо класс:

PHP
$schedule->command('emails:send —force')->daily();

$schedule->command(EmailsCommand::class, ['--force'])->daily();

Команда PHPexec() может быть использована для обращения к операционной системе:

PHP
$schedule->exec('node /home/forge/script.js')->daily();

Настройки частоты планировщика

Конечно, есть множество вариантов планировщика, которые вы можете назначить на свою задачу:

Метод Описание
->cron('* * * * * *');Запускать задачу по пользовательскому расписанию
->everyMinute();Запускать задачу каждую минуту
->everyFiveMinutes();Запускать задачу каждые 5 минут
->everyTenMinutes();Запускать задачу каждые 10 минут
->everyThirtyMinutes();Запускать задачу каждые 30 минут
->hourly();Запускать задачу каждый час
->hourlyAt(17);Запускать задачу каждый час в хх:17 минут (для версии 5.3 и выше)
->daily();Запускать задачу каждый день в полночь
->dailyAt('13:00');Запускать задачу каждый день в 13:00
->twiceDaily(1, 13);Запускать задачу каждый день в 1:00 и 13:00
->weekly();Запускать задачу каждую неделю
->monthly();Запускать задачу каждый месяц
->monthlyOn(4, '15:00');Запускать задачу 4 числа каждого месяца в 15:00 (для версии 5.2 и выше)
->quarterly();Запускать задачу каждые 3 месяца (для версии 5.2 и выше)
->yearly();Запускать задачу каждый год
->timezone('America/New_York');Задать часовой пояс (для версии 5.2 и выше)

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

PHP
// Запуск каждый понедельник в 13:00...
$schedule->call(function () {
  
//
})->weekly()->mondays()->at('13:00');
+ 5.3 5.2

добавлено в 5.3 () 5.2 ()

PHP
// Запускать каждый час с 8:00 до 17:00 по будням...
$schedule->command('foo')
         ->
weekdays()
         ->
hourly()
         ->
timezone('America/Chicago')
         ->
between('8:00''17:00');

Ниже приведён список дополнительных ограничений в расписании:

Метод Описание
->weekdays();Ограничить задачу рабочими днями
->sundays();Ограничить задачу воскресеньем
->mondays();Ограничить задачу понедельником
->tuesdays();Ограничить задачу вторником
->wednesdays();Ограничить задачу средой
->thursdays();Ограничить задачу четвергом
->fridays();Ограничить задачу пятницей
->saturdays();Ограничить задачу субботой
->between($start, $end);Ограничить запуск задачи между временем начала и конца промежутка (для версии 5.3 и выше)
->when(Closure);Ограничить задачу на основе успешного теста
+ 5.3

добавлено в 5.3 ()

Ограничение промежутком времени

Методом PHPbetween() можно ограничить выполнение задачи в зависимости от времени дня:

PHP
$schedule->command('reminders:send')
         ->
hourly()
         ->
between('7:00''22:00');

А методом PHPunlessBetween() можно исключить выполнение задачи в указанный период времени:

PHP
$schedule->command('reminders:send')
         ->
hourly()
         ->
unlessBetween('23:00''4:00');

Ограничения успешного теста

Метод PHPwhen() может быть использован, чтобы ограничить выполнение задачи на основании результата успешно пройденного теста. Другими словами, если заданное PHPClosure возвращает true, задача будет выполняться до тех пор, пока никакие другие ограничивающие условия не препятствуют её выполнению:

PHP
$schedule->command('emails:send')->daily()->when(function () {
  return 
true;
});
+ 5.2

добавлено в 5.2 ()

Метод PHPskip() является инверсией метода PHPwhen(). Если метод PHPskip() возвращает true, запланированная задача не будет запущена:

PHP
$schedule->command('emails:send')->daily()->skip(function () {
  return 
true;
});

При использовании сцепленного метода PHPwhen(), запланированная команда выполнится только при условии, что все PHPwhen() возвратят true.

Предотвращение перекрытий задач

По умолчанию, запланированные задачи будут запускаться, даже если предыдущий экземпляр задачи всё ещё выполняется. Чтобы предотвратить это, вы можете использовать метод PHPwithoutOverlapping():

PHP
$schedule->command('emails:send')->withoutOverlapping();

В этом примере Artisan-команда shemails:send будет запускаться каждую минуту, если она ещё не запущена. Метод PHPwithoutOverlapping() особенно полезен, если у вас есть задачи, которые изменяются коренным образом во время своего выполнения, что мешает вам предсказывать точно, сколько времени данная задача будет выполняться.

+ 5.3

добавлено в 5.3 ()

Режим обслуживания

Запланированные задачи Laravel не будут запускаться, когда Laravel находится в режиме обслуживания, так как мы не хотим, чтобы ваши команды столкнулись с какими-либо незаконченными операциями обслуживания сервера. Но если вы хотите, чтобы задача запускалась даже в режиме обслуживания, вы можете использовать метод PHPevenInMaintenanceMode():

PHP
$schedule->command('emails:send')->evenInMaintenanceMode();

Выходные данные задачи

Планировщик Laravel предоставляет несколько удобных методов для работы с выходными данными, сгенерированными запланированными задачами. Во-первых, используя метод PHPsendOutputTo(), вы можете отправить вывод данных в файл для последующего анализа:

PHP
$schedule->command('emails:send')
         ->
daily()
         ->
sendOutputTo($filePath);

Если вы хотите добавить вывод в указанный файл, вы можете использовать метод PHPappendOutputTo():

PHP
$schedule->command('emails:send')
         ->
daily()
         ->
appendOutputTo($filePath);

Используя метод PHPemailOutputTo(), вы можете отправить по электронной почте выходные данные на адрес по вашему усмотрению. Обратите внимание, что данные должны быть сначала отправлены в файл с помощью метода PHPsendOutputTo(). Перед отправкой на электронную почту результата выполнения задачи вы должны настроить службы электронной почты Laravel:

PHP
$schedule->command('foo')
         ->
daily()
         ->
sendOutputTo($filePath)
         ->
emailOutputTo('foo@example.com');

Методы PHPemailOutputTo(), PHPsendOutputTo() и PHPappendOutputTo() доступны исключительно для метода PHPcommand() и не поддерживаются для PHPcall().

Обработчики прерываний задач

Используя методы PHPbefore() и PHPafter(), вы можете указать код, который будет выполняться до запуска и после завершения запланированной задачи:

PHP
$schedule->command('emails:send')
         ->
daily()
         ->
before(function () {
           
// Перед запуском задачи...
         
})
         ->
after(function () {
           
// Задача завершена...
         
});

Пинг URL-адресов

Используя методы PHPpingBefore() и PHPthenPing(), планировщик может автоматически пинговать заданный URL до запуска и после завершения задачи. Этот метод полезен для уведомления внешней службы, например, Laravel Envoyer, о том, что ваша запланированная задача запустилась или закончила выполнение:

PHP
$schedule->command('emails:send')
         ->
daily()
         ->
pingBefore($url)
         ->
thenPing($url);

Использование функций PHPpingBefore($url) или PHPthenPing($url) требует библиотеки Guzzle HTTP.

+ 5.3

добавлено в 5.3 ()

Вы можете добавить Guzzle к вашему проекту с помощью менеджера пакетов Composer:

shcomposer require guzzlehttp/guzzle
+ 5.2 5.1

добавлено в 5.2 () 5.1 ()

Вы можете добавить Guzzle к вашему проекту, добавив следующую строку в файл composer.json:

"guzzlehttp/guzzle": "~5.3|~6.0"

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

Sawa4

Всем привет! У вас заработал крон? Я делаю так:

*  *    * * *   root    /usr/bin/php /var/www/site.name/artisan schedule:run » /dev/null 2>&1

Но у меня не работает почему то на Debian 7.8, что я делаю не так?

Proger_XP

В статье >> стало кавычками, посмотри внимательно на свой код.

schedule:run » /dev
-------------^
Sawa4

это не то что я ищу, тут нарыл (точнее один умный человек сказал), что под рутом вообще нельзя ничего запускать никогда, так что в etc/crontab добавлять не вариант

Proger_XP

В crontab указывается пользователь (после звездочек), обычно это www-data, см. конфиг Apache/nginx/php, какой там пользователь.

Также можно использовать crontab -eu www-data для правки конфига пльзователья.

Sawa4

у меня Debian там пишу так /var/spool/cron/crontab/fileusername и тут без указание пользователя, проблема следующая, которая ниже в комменте

Sawa4

Вообщем понял одно Если писать просто $schedule->command('backup:run'); то пашет, а если $schedule->command('backup:run')->dailyAt('11:00'); или $schedule->command('backup:run')->daily()->at('11:00'); то не работает. Кто знает почему такое возможно?

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.