在 Laravel 5.5 框架中使用计划任务
最近在用 Laravel 5.5 做的 YunLoad 项目中需要有一个提交任务自动截止功能需要用到计划任务,任务逻辑是在每天凌晨检查一次添加的提交任务是否已经过期,若已过期则自动将提交任务标记为 “已过期”. Google 了很久也没能发现一个完整的教程,Laravel 相关文档也写得含糊其词,遂记录一下我的操作过程。
创建 Command
作为计划任务,我们需要的是 command
(而不是网上说的 console),相关命令如下:
$ php artisan make:command CheckDeadline
此时会在 /app/Console/Commands/
下创建一个 CheckDeadline.php
文件,我们需要在这个文件的 handle
函数中定义我们的需要的操作,如果代码设计 Model
操作的话需要在文件顶部声明(本例中需要 use Carbon\Carbon
),部分代码如下:
...
protected $signature = 'CheckDeadline:checkdeadline';// Define the Command name
...
public function handle()
{
// Get the non-ended courses as $courses array
foreach($courses as $course){
// $dl for Parse the course setted deadline
if($dl->isPast()){
// Mark the Course ended, update database...
$this->info('Course'.$course->id.'hitted deadline, ended.');
}
}
}
在 Console Kernel 中注册这个 Command
在 /app/Console/Kernel.php
中注册这个 Commmand,部分代码如下:
protected $commands = ['\App\Console\Commands\CheckDeadline',];
protected function schedule(Schedule $schedule)
{$schedule->command('checkdeadline')->daily();}
其中 daily()
表示每天凌晨执行,更多频率关键词可以参考 官方文档.
写好了之后我们测试一下:
➜ php artisan CheckDeadline:checkdeadline
Course 6 hitted deadline, ended.
Course 13 hitted deadline, ended.
跑起来了,看来没问题,我们把代码部署到服务器上面去并让他自己定期跑~
让系统的 crontab 定期拉起 Laravel
在部署好了相关文件后我们需要用 Linux 的 crontab 定期拉起 Laravel 来让 artisan
去执行我们的计划任务,新建个计划任务,然后如下编写:
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
需要注意的是,这里的 PHP 需要写绝对路径,如果不清楚的话建议先 whereis php
之后确认一下,比如我本地实验环境:
➜ whereis php
php: /usr/bin/php /usr/lib64/php /etc/php.ini /etc/php.d /usr/share/php /usr/share/man/man1/php.1.gz
➜ /usr/bin/php --version
PHP 7.1.16 (cli) (built: Mar 28 2018 07:11:55) (NTS)
...
那就需要写成(假设项目在 / var/www/yunload 下)
* * * * * /usr/bin/php /var/www/yunload/artisan schedule:run >> /dev/null 2>&1
2018-05-30 更新:似乎按照上面得写法 Laravel 调用的 command 时用的 artisan 不是绝对路径,这样会失败,目前我使用的方法如下:
@hourly /usr/bin/php /var/www/yunload/artisan CheckDeadline:checkdeadline >> /dev/null 2>&1
不过我有一个疑问,Wordpress 中可以定时自动发布文章,我们在安装 Wordpress 的时候并不需要利用系统的 crontab,那它们是如何实现的呢?或者说,为什么 Laravel 就必须要用系统 crontab 才能实现计划任务呢?