[ Laravel 5.6 文档 ] 进阶系列 —— 任务调度

简介

Cron 是 UNIX、SOLARIS、LINUX 下的一个十分有用的工具,通过 Cron 脚本能使计划任务定期地在系统后台自动运行。这种计划任务在 UNIX、SOLARIS、LINUX下术语为 Cron Jobs。Crontab 则是用来记录在特定时间运行的 Cron 的一个脚本文件,Crontab 文件的每一行均遵守特定的格式:

?

我们可以在服务器上通过 crontab -e 来新增或编辑 Cron 条目,通过 crontab -l 查看已存在的 Cron 条目。更多关于 Cron 的原理和使用细节请自行百度或 Google。

在以前,开发者需要为每一个需要调度的任务编写一个 Cron 条目,这是很让人头疼的事。你的任务调度不在源码控制中,你必须使用 SSH 登录到服务器然后添加这些 Cron 条目。

Laravel 命令调度器允许你流式而又不失优雅地在 Laravel 中定义命令调度,并且服务器上只需要一个 Cron 条目即可。任务调度定义在 app/Console/Kernel.php 文件的 schedule 方法中,该方法中已经包含了一个示例。

开启调度器

下面是你唯一需要添加到服务器的 Cron 条目,如果你不知道如何添加 Cron 条目到服务器,可以考虑使用诸如 Laravel Forge 这样的服务来为管理 Cron 条目:

* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

该 Cron 将会每分钟调用一次 Laravel 命令调度器,当 schedule:run 命令执行后,Laravel 评估你的调度任务并运行到期的任务。

定义调度

你可以在 App\Console\Kernel 类的 schedule 方法中定义所有调度任务。让我们从一个调度任务的例子开始,在这个例子中,我们将会在每天午夜调度一个被调用的闭包。在这个闭包中我们将会执行一个数据库操作来清空表:

<?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 = [
        //
    ];

    /**
     * 定义应用的命令调度
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     * @translator laravelacademy.org
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            DB::table(‘recent_users‘)->delete();
        })->daily();
    }
}

调度 Artisan 命令

除了调度闭包调用外,还可以调度 Artisan 命令和操作系统命令。例如,可以使用 command 方法通过命令名或类来调度一个 Artisan 命令:

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

调度队列任务

job 方法可用于调度一个队列任务,通过该方法可以很方便地调度任务而不必调用 call 方法手动创建闭包来推送任务到队列:

$schedule->job(new Heartbeat)->everyFiveMinutes();

调度 Shell 命令

exec 方法可用于调用操作系统命令:

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

调度常用选项

当然,你可以分配多种调度到任务:

方法 描述
->cron(‘* * * * *‘); 在自定义Cron调度上运行任务
->everyMinute(); 每分钟运行一次任务
->everyFiveMinutes(); 每五分钟运行一次任务
->everyTenMinutes(); 每十分钟运行一次任务
->everyFifteenMinutes(); 每十五分钟运行一次任务
->everyThirtyMinutes(); 每三十分钟运行一次任务
->hourly(); 每小时运行一次任务
->hourlyAt(17); 每小时第十七分钟运行一次任务
->daily(); 每天凌晨零点运行任务
->dailyAt(‘13:00‘); 每天13:00运行任务
->twiceDaily(1, 13); 每天1:00 & 13:00运行任务
->weekly(); 每周运行一次任务
->monthly(); 每月运行一次任务
->monthlyOn(4, ‘15:00‘); 每月4号15:00运行一次任务
->quarterly(); 每个季度运行一次
->yearly(); 每年运行一次
->timezone(‘America/New_York‘); 设置时区

这些方法可以和额外的约束一起联合起来创建一周特定时间运行的、更加细粒度的调度,例如,要在每周一调度一个命令:

$schedule->call(function () {
    // 每周星期一13:00运行一次...
})->weekly()->mondays()->at(‘13:00‘);

// 工作日的上午8点到下午5点每小时运行...
$schedule->command(‘foo‘)
         ->weekdays()
         ->hourly()
         ->timezone(‘America/Chicago‘)
         ->between(‘8:00‘, ‘17:00‘);

下面是额外的调度约束列表:

方法 描述
->weekdays(); 只在工作日运行任务
->sundays(); 每个星期天运行任务
->mondays(); 每个星期一运行任务
->tuesdays(); 每个星期二运行任务
->wednesdays(); 每个星期三运行任务
->thursdays(); 每个星期四运行任务
->fridays(); 每个星期五运行任务
->saturdays(); 每个星期六运行任务
->between($start, $end); 基于特定时间段运行任务
->when(Closure); 基于特定测试运行任务

介于时间的约束条件

between 方法用于限定一天中特定时间段的任务执行:

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

类似地,unlessBetween 方法用于排除指定时间段任务的执行:

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

真理测试的约束条件

when 方法用于限制任务基于给定真理测试的结果执行。换句话说,如果给定闭包返回true,只要没有其它约束条件阻止任务运行,该任务就会执行:

$schedule->command(‘emails:send‘)->daily()->when(function () {
    return true;
});

skip 方法和 when 相反,如果 skip 方法返回true,调度任务将不会执行:

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

使用 when 方法链的时候,调度命令将只会执行返回 true 的 when 方法。

时区

使用 timezone 方法你可以指定调度任务的执行时间在给定时区内切换:

$schedule->command(‘report:generate‘)
     ->timezone(‘America/New_York‘)
     ->at(‘02:00‘)

注:请记住有些时区会使用夏令时,当夏令时改变时,你的调度任务有可能会运行两次或者根本不会运行,因此,建议你最好不要使用这种时区调度。

避免任务重叠

默认情况下,即使前一个任务仍然在运行调度任务也会运行,要避免这样的情况,可使用 withoutOverlapping 方法:

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

在本例中,Artisan 命令 emails:send 每分钟都会运行 —— 如果该命令没有在运行的话。如果你的任务在执行时经常大幅度的变化,那么 withoutOverlapping 方法就非常有用,你不必再去预测给定任务到底要消耗多长时间。

如果需要的话,你可以指定”without overlapping”锁失效前的分钟数,默认情况下,这个锁会在 24 小时后失效:

$schedule->command(‘emails:send‘)->withoutOverlapping(10);

在单台服务器上运行任务

注:要使用这个功能,必须使用 memcached 或 redis 缓存驱动作为应用默认的缓存驱动。此外,所有服务器必须和同一个中央缓存服务器通信。

如果你的应用运行在多台服务器上,可能需要限制调度任务只在某台服务器上运行。例如,假设你有一个每个星期五晚上生成新报告的调度任务,如果任务调度器运行在三台服务器上,调度任务会在三台服务器上运行并且生成三次报告,不够优雅!

要告知任务只在单台服务器上运行,在定义调度任务时使用 onOneServer 方法即可。第一台获取到该任务的服务器会给任务上一把原子锁以阻止其他服务器同时运行该任务:

$schedule->command(‘report:generate‘)
            ->fridays()
            ->at(‘17:00‘)
            ->onOneServer();

维护模式

当 Laravel 处于维护模式时,调度任务不会运行,不过,如果你想要在维护模式期间强制运行任务,可以使用 evenInMaintenanceMode 方法:

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

任务输出

Laravel 调度器为处理调度任务输出提供了多个方便的方法。首先,使用sendOutputTo 方法,你可以发送输出到文件以便稍后检查:

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

如果你想要追加输出到给定文件,可以使用 appendOutputTo 方法:

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

使用 emailOutputTo 方法,你可以将输出通过邮件发送给接收人。使用邮件发送任务输出之前,需要配置 Laravel 的邮件服务

$schedule->command(‘foo‘)
     ->daily()
     ->sendOutputTo($filePath)
     ->emailOutputTo(‘[email protected]‘);

注:emailOutputTosendOutputTo 和 appendOutputTo 方法只对 command 和 exec 方法有效。

任务钩子

使用 before 和 after 方法,你可以指定在调度任务完成之前和之后要执行的代码:

$schedule->command(‘emails:send‘)
         ->daily()
         ->before(function () {
             // 任务即将开始...
         })
         ->after(function () {
             // 任务已经完成...
         });

Ping URL

使用 pingBefore 和 thenPing方法,调度器可以在任务完成之前和之后自动 ping 给定的 URL。该方法在通知外部服务时很有用,例如 Laravel Envoyer,在调度任务开始或完成的时候:

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

使用 pingBefore($url) 或 thenPing($url) 特性需要安装 HTTP 库 Guzzle,可以使用 Composer 包管理器来安装 Guzzle 依赖到项目:

composer require guzzlehttp/guzzle

原文地址:https://www.cnblogs.com/jjxhp/p/9193278.html

时间: 2024-10-10 04:16:16

[ Laravel 5.6 文档 ] 进阶系列 —— 任务调度的相关文章

JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载

JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载JDK(Java Development Kit,Java开发包,Java开发工具)是一个写Java的applet和应用程序的程序开发环境.它由一个处于操作系统层之上的运行环境还有开发者编译,调试和运行用Java语言写的applet和应用程序所需的工具组成. JDK(Java Development Kit)是Sun Microsystems针对Java开发员的产品.自从Java推出以来,JDK已经成为使用最广泛

[ Laravel 5.5 文档 ] 处理用户请求 —— HTTP 请求的过滤器:中间件

[ Laravel 5.5 文档 ] 处理用户请求 -- HTTP 请求的过滤器:中间件 http://laravelacademy.org/post/7812.html 简介 中间件为过滤进入应用的 HTTP 请求提供了一套便利的机制.例如,Laravel 内置了一个中间件来验证用户是否经过认证(如登录),如果用户没有经过认证,中间件会将用户重定向到登录页面,而如果用户已经经过认证,中间件就会允许请求继续往前进入下一步操作. 当然,除了认证之外,中间件还可以被用来处理很多其它任务.比如:COR

Laravel生成Word文档 - phpword

在项目实际开发或学习中,会遇到把数据导出生成word文档的需求.这里就用优雅.流行的laravel框架,来简单的教大家实现. phpword,它可以很方便的实现word文档的生成,同时可以在word中添加表格.目录.图片.超链接.页眉.页脚等功能强大. 安装phpWord 要求 强制性: PHP 5.3.3+ XML解析器扩展 Zend \ Escaper组件 Zend \ Stdlib组件 Zend \ Validator组件 可选的: -邮编扩展 - GD扩展 - XMLWriter扩展 -

Laravel 5.1 文档攻略 —— Eloquent:模型对象序列化

在写api的时候,数据一般是以json格式进行传输的,没有对象可以直接使用.这个时候,对数据的序列化转换就很重要,Eloquent提供了很方便的方法和约定,不仅可以转换,还可以控制里面的键值. 基本用法 将模型转化为数组 $user = App\User::with('roles')->first(); return $user->toArray(); 把一个模型转化成数组: $users = App\User::all(); return $users->toArray(); 把col

[ Laravel 5.1 文档 ] 服务 —— 任务调度

1.简介 在以前,开发者需要为每一个需要调度的任务编写一个Cron条目,这是很让人头疼的事.你的任务调度不在源码控制中,你必须使用SSH登录到服务器然后添加这些Cron条目.Laravel命令调度器允许你平滑而又富有表现力地在Laravel中定义命令调度,并且服务器上只需要一个Cron条目即可. 任务调度定义在app/Console/Kernel.php文件的schedule方法中,该方法中已经包含了一个示例.你可以自由地添加你需要的调度任务到Schedule对象. 1.1 开启调度 下面是你唯

[ Laravel 5.1 文档 ] 架构 —— 应用目录结构

1.简介 Laravel应用默认的目录结构试图为不管是大型应用还是小型应用提供一个好的起点,当然,你可以自己按照喜好重新组织应用目录结构,Laravel对类在何处被加载没有任何限制——只要Composer可以自动载入它们即可. 2.根目录 新安装的Laravel应用包含许多文件夹: app目录包含了应用的核心代码: bootstrap目录包含了少许文件用于框架的启动和自动载入配置,还有一个cache文件夹用于包含框架生成的启动文件以提高性能: config目录包含了应用所有的配置文件: data

java帮助文档下载

JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载JDK(Java Development Kit,Java开发包,Java开发工具)是一个写Java的applet和应用程序的程序开发环境.它由一个处于操作系统层之上的运行环境还有开发者编译,调试和运行用Java语言写的applet和应用程序所需的工具组成. JDK(Java Development Kit)是Sun Microsystems针对Java开发员的产品.自从Java推出以来,JDK已经成为使用最广泛

Java SE之XML&lt;一&gt;XML文档规约

[文档整理系列] Java SE之XML<一>XML文档规约 1.xml文档引用: 1.外部私有DTD: <!DOCTYPE rootNodeName SYSTEM "uri.dtd"> (在xml文件中声明,带关键字SYSTEM) 2.外部公共文件时: <!DOCTYPE rootNode名称 PUBLIC "DTD名称" "uri.dtd"> (在xml文件中声明,带关键字PUBLIC) 3.内部引用: &

第一百一十四节,JavaScript文档对象,DOM进阶

JavaScript文档对象,DOM进阶 学习要点: 1.DOM类型 2.DOM扩展 3.DOM操作内容