Task scheduling
- Define the schedule
- Artisan Command Scheduling
- Shell command scheduling
- Scheduling frequency setting
- Time range restrictions
- Closure test restrictions
- Environmental constraints
- Background tasks
- Maintenance mode
- ##Task output
- Task Hook
- Ping URL
Task Scheduling
Introduction
In the past, you might need to create a new thread for each task on the server. Schedule tasks to create Cron entries. But this approach quickly becomes unfriendly because these task schedulers are not in the source code, and you need to log into the server through an SSH link every time to add a Cron entry.
Laravel command line scheduler allows you to clearly and smoothly define command scheduling in Laravel. And when using this task scheduler, you only need to create a single Cron entry interface on your server. Your task schedule is defined in the
schedule
method ofapp/Console/Kernel.php
. To help you get started, here is a simple example in this method.Start the scheduler
When using this scheduler, you only need to add the following Cron entry to your server. If you don’t know how to add a Cron entry to the server, you can consider using some services to manage Cron entries, such as Laravel Forge:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
This Cron is a command line that executes Laravel once every minute scheduler. When the
schedule:run
command is executed, Laravel will execute the scheduled program according to your schedule.Define scheduling
You can do this in the
App\Console\Kernel
class #scheduledefines all scheduling tasks in the method. Before we begin, let's look at an example. In this example, we plan to call a closure every day at midnight. In a closure, we execute a database query to clear a table:
<?php namespace App\Console; use Illuminate\Support\Facades\DB; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel{ /** * 应用里的自定义 Artisan 命令 * * @var array */ protected $commands = [ // ]; /** * 定义计划任务 * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->call(function () { DB::table('recent_users')->delete(); })->daily(); } }
In addition to using closures to define task scheduling, you can also useinvokable objects.
$schedule->call(new DeleteRecentUsers)->daily();
Artisan Command Scheduling
In addition to scheduling by calling closures, you can also call Artisan commands and operating system commands. For example, you can schedule an Artisan command by passing the command name or class to the
command
method.$schedule->command('emails:send --force')->daily(); $schedule->command(EmailsCommand::class, ['--force'])->daily();
Queue task scheduling
job
method can be used to schedule queue tasks. This method provides a quick way to schedule tasks without having to create a closure using thecall
method to schedule tasks.$schedule->job(new Heartbeat)->everyFiveMinutes(); // 分发任务到「heartbeats」队列... $schedule->job(new Heartbeat, 'heartbeats')->everyFiveMinutes();
Shell Command Scheduling
exec
method can be used to send commands to the operating system:$schedule->exec('node /home/forge/script.js')->daily();
Scheduling frequency setting
Of course, you can assign multiple scheduling plans to your tasks:
Method Description ##->cron('* * * * *'); Customized Cron schedule execution task->everyMinute(); Perform a task every minute->everyFiveMinutes(); Perform a task every five minutes->everyTenMinutes(); Perform a task every ten minutes##->everyFifteenMinutes (); Perform a task every fifteen minutes
->everyThirtyMinutes(); Execute the task every thirty minutes
->hourly(); Execute the task every hour
->hourlyAt(17); Execute the task at the 17th minute every hour
-> ;daily(); Perform a task every day at midnight (Translator's Note: Every day at midnight)
->dailyAt('13: 00'); ##->twiceDaily(1, 13);Execute the task once every day at 13:00
->weekly();Execute tasks once every day at 1:00 and 13:00
Execute tasks once a week
##->weeklyOn(1, '8:00'); Execute a task every Monday at 8 o'clock ->monthly();
Perform the task once a month ->monthlyOn( 4, '15:00');
Execute the task at 15:00 on the 4th of every month ->quarterly();
Perform a task every quarter ->yearly();
Perform a task once a year ##->timezone('America/New_York'); Set time zoneCombined with some other specific conditions, we can generate tasks that run at specific times of the week. For example, execute the command every Monday:
// 每周一 13:00 执行... $schedule->call(function () { // })->weekly()->mondays()->at('13:00'); // 工作日(周一至周五) 8点 至 17 点每小时执行一次... $schedule->command('foo') ->weekdays() ->hourly() ->timezone('America/Chicago') ->between('8:00', '17:00');
The additional restriction list is as follows:
Method Description ->weekdays();
Restrict tasks to be executed on working days ->weekends();
Restrict tasks to be executed on weekends ->sundays();
Restrict tasks to be executed on Sunday ->mondays();
Restrict tasks to be executed on Mondays ##->tuesdays(); Restrict tasks to be executed on Tuesdays->wednesdays(); Restrict tasks to be executed on Wednesdays->thursdays(); Restrict tasks to be executed on Thursday##->fridays(); Restrict tasks to be executed on Friday
->saturdays(); ##-> between($start, $end);Restrict tasks to be executed on Saturdays
->when(Closure); andRestrict tasks to be executed between
$start$end Executed when the closure returns true
##->environments ($env); Restrict tasks to be executed in a specific environment Time range restriction
Use
between
to limit the task execution to a certain time period of the day:$schedule->command('reminders:send') ->hourly() ->between('7:00', '22:00');
or use
unlessBetween
Method to exclude a time period for a task:$schedule->command('reminders:send') ->hourly() ->unlessBetween('23:00', '4:00');
Closure test limit
Use the
when
method to based on the test results to perform the task. That is to say, if the given closure returnstrue
, the task will continue to execute as long as there are no other constraints that prevent the task from running:$schedule->command('emails:send')->daily()->when(function () { return true; });
skip## The # method can be seen as the reverse process of the
whenmethod. If the
skipmethod returns
true, the task will not be executed:
$schedule->command('emails:send')->daily()->skip(function () { return true; });
When using the chained callwhen
Environment Constraintsmethod, only all
Whenreturns
true, the task will be executed.
environments
Methods can be used to perform tasks only in a given environment:
$schedule->command('emails:send') ->daily() ->environments(['staging', 'production']);
Time ZoneUsing thetimezone
method, you can specify that the task executes in a given time zone:
$schedule->command('report:generate') ->timezone('America/New_York') ->at('02:00')
If you want to assign the same time zone to all scheduled tasks, you may want to define thescheduleTimezone
method in the
app/Console/Kernel.phpfile. This method should return the default time zone that should be assigned to all scheduled tasks:
/** * 获取默认情况下应为预定事件使用的时区。 * * @return \DateTimeZone|string|null */ protected function scheduleTimezone(){ return 'America/Chicago'; }
{note} Keep in mind that some time zones use daylight saving time. When daylight saving time changes, your task may execute twice or not at all. So we recommend avoiding using time zones to schedule scheduled tasks whenever possible.
Avoid task duplicationBy default, even if the previous task is still executing, the schedule will The task will also be executed. You can avoid this using thewithoutOverlapping
method:
$schedule->command('emails:send')->withoutOverlapping();
In this example, if theemails:send
If necessary, you can specify the "without overlapping" lock for the specified time range. By default, locks expire after 24 hours.Artisan command is not running, it will be sent every minute Execute once. If your task execution time is uncertain and you cannot accurately estimate the task execution time, then the
withoutOverlappingmethod will be particularly useful.
$schedule->command('emails:send')->withoutOverlapping(10);
The task only runs on one server
{note} To use this feature, your application's default cache driver must be
memcached
orredis
. In addition, all servers must communicate using the same central cache server.If your application runs on multiple servers, you may need to limit your scheduled tasks to only run on a single server. Let's say you have a schedule that generates a new report every Friday night. If the task scheduler runs on three servers, then the task will run on three servers and generate three reports. this is not good!
To indicate that the task should run on a single server, use the
onOneServer
method when defining the scheduled task. The first server to obtain the task will generate an atomic lock to prevent other servers from executing the same task at the same time.$schedule->command('report:generate') ->fridays() ->at('17:00') ->onOneServer();
Background Tasks
By default, multiple commands scheduled at the same time will be executed sequentially. If you have long-running commands, this may cause subsequent commands to start later than expected. Therefore, if you want to run commands simultaneously in the background, you can use the
runInBackground
method:$schedule->command('analytics:report') ->daily() ->runInBackground();
##Maintenance ModeLaravel's queue tasks will not run in maintenance mode. Because we don't want your scheduling tasks to interfere with projects that may not be completed on your server. However, if you really want to force scheduled task execution in maintenance mode, you can use theevenInMaintenanceMode
method:
$schedule->command('emails:send')->evenInMaintenanceMode();
sendOutputTo
method to output to a file for later inspection:
$schedule->command('emails:send') ->daily() ->sendOutputTo($filePath);
If you wish to append the outputto a given file, you can use
appendOutputTomethod
$schedule->command('emails:send') ->daily() ->appendOutputTo($filePath);
Using theemailOutputTo
method, you can send the output to the specified mailbox. Before using email to send, you need to configure Laravel's email service:
$schedule->command('foo') ->daily() ->sendOutputTo($filePath) ->emailOutputTo('foo@example.com');
{note}
emailOutputTo
,
sendOutputToand
appendOutputToMethods are unique to
commandand
exec.
##Task hookUse
beforeand
after
Method, you can execute specific code before or after the scheduled task is executed:$schedule->command('emails:send') ->daily() ->before(function () { // Task is about to start... }) ->after(function () { // Task is complete... });
Ping URL
Using the
pingBefore
andthenPing
methods, you can ping the specified URL before or after task execution. This method will be particularly useful when notifying external services (such as Laravel Envoyer):$schedule->command('emails:send') ->daily() ->pingBefore($url) ->thenPing($url);
Can only be used if the given condition is
true
The pingBeforeIf
andthenPingIf
methods ping the specified URL:$schedule->command('emails:send') ->daily() ->pingBeforeIf($condition, $url) ->thenPingIf($condition, $url);
All ping methods require the Guzzle HTTP library. You can use Composer to add Guzzle to your project:
composer require guzzlehttp/guzzle
This article was first published on the LearnKu.com website.← queue