简介

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('foo@example.com');

注: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

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

  1. [ Laravel 5.6 文档 ] 安全系列 —— 重置密码

    http://laravelacademy.org/post/8929.html 简介 想要快速实现该功能?只需要在新安装的 Laravel 应用下运行 php artisan make:auth(如 ...

  2. SharePoint 2010 文档管理系列

    前言,这是自己第一次写一个系列的文档,本来想使用SharePoint 2013版本,但是碍于SharePoint 2013对于硬件要求过高,自己的笔记本无法承受,所以退而求其次选择了在SharePoi ...

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

    JAVA帮助文档全系列 JDK1.5 JDK1.6 JDK1.7 官方中英完整版下载JDK(Java Development Kit,Java开发包,Java开发工具)是一个写Java的applet和 ...

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

    [ Laravel 5.5 文档 ] 处理用户请求 —— HTTP 请求的过滤器:中间件 http://laravelacademy.org/post/7812.html 简介 中间件为过滤进入应用的 ...

  5. SharePoint 2010 文档管理系列之准备篇

    前言:很早自己就想写一个系列的文章,但是不知道写什么,最近在QQ群里,好多人说在做文档管理,其实文档管理也是SharePoint的一个很不错的功能点,自己想了想,也想多学习点东西,所以写这个主题吧,今 ...

  6. [ Laravel 5.5 文档 ] 快速入门 —— 目录结构篇

    简介 Laravel 默认的目录结构试图为不管是大型应用还是小型应用提供一个良好的起点.当然,你也可以按照自己的喜好重新组织应用的目录结构,因为 Laravel 对于指定类在何处被加载没有任何限制 — ...

  7. Laravel 5.5 文档 ] 快速入门 —— 安装配置篇

    服务器要求 Laravel 框架对PHP版本和扩展有一定要求,不过这些要求 Laravel Homestead 都已经满足了,不过如果你没有使用 Homestead 的话(那真是一件很遗憾的事情),有 ...

  8. [ Laravel 5.5 文档 ] 底层原理 —— 一次 Laravel 请求的生命周期

     Posted on 2018年3月5日 by  学院君 简介 当我们使用现实世界中的任何工具时,如果理解了该工具的工作原理,那么用起来就会得心应手,应用开发也是如此.当你理解了开发工具如何工作,用起 ...

  9. SharePoint 2010 文档管理系列之文档搜索

    前言:如果一个文档库里面有很多文档,成千上万,对我们来说查找就是个麻烦事儿,所以搜索的必要性就体现出来了.下面,我们简单的介绍下,sharepoint搜索配置,并创建一个简单的搜索页面. 一. 配置S ...

随机推荐

  1. 基于jQuery1.4.2轻量级的弹出窗口jQuery插件wBox 1.0

    Box特点 背景透明度可以根据实际情况进行调节 可以根据需要添加wBox标题 支持callback函数 支持html内容自定义 支持在wBox显示#ID的内容 支持Ajax页面内容 支持iFrame ...

  2. Java 查找算法

    1 查找算法介绍 在 java 中,我们常用的查找有四种: 1) 顺序(线性)查找 2) 二分查找/折半查找 3) 插值查找 4) 斐波那契查找   2 线性查找算法 有一个数列: {1,8, 10, ...

  3. 进阶宝典一|SqlServer数据库自动备份设置

    很多人都没机会接触到数据库备份,经常操作的要么是数据库管理员,要么是项目负责人.那是不是说数据库备份就不用学了? 不,其实作为开发人员应该要了解数据备份,数据备份的手段有很多:软件备份.脚本备份.其他 ...

  4. 如何自己配置pip源

    方式一:临时使用国内pypi镜像安装 pip install -i http://pypi.douban.com/simple/ numpy pip install -i http://pypi.do ...

  5. C# 应用 - 多线程 5) 死锁

    两个线程中的每一个线程都尝试锁定另外一个线程已锁定的资源时,就会发生死锁. 两个线程都不能继续执行. 托管线程处理类的许多方法都提供了超时设定,有助于检测死锁. 例如,下面的代码尝试在 lockObj ...

  6. [POJ2828] Buy Tickets(待续)

    [POJ2828] Buy Tickets(待续) 题目大意:多组测试,每组给出\(n\)条信息\((a,b)\),表示\(b\)前面有\(a\)个人,顺序靠后的信息优先级高 Solution.1 由 ...

  7. dfs求连通块

    递归 递归是什么?绝大部分人都会说:自己调用自己,刚开始我也是这样理解递归的.确实没错,递归的确是自己调用自己.递归简单的应用:编写一个能计算斐波那契数列的函数,也就是这样: int fb(int n ...

  8. java重写toString()方法

    toString()方法是Object类的方法,调用toString()会返回对象的描述信息. 1)为什么重写toString()方法呢? 如果不重写,直接调用Object类的toString()方法 ...

  9. vim命令c编程

    1.移动光标的常用命令 h--向左移动光标 l--向右移动光标 j--向下移动光标 k--向上移动光标 ^--将光标移动至该行的开头 $--将光标移动至该行的结尾 O--将光标移动至该行行首 G--将 ...

  10. Java系列教程-MyBatis 3.5.5 教程目录

    MyBatis 3.5.5 初级教程目录 可参考MyBatis的官方文档也比较清楚 https://mybatis.org/mybatis-3/zh/getting-started.html 代码 目 ...