laravel-任务调度-d

作者:Shine 发布于:2018-03-25 22:56:48 浏览:1117次 分类:PHP

laravel-任务调度

       开头先说一下平时在项目中定时任务的写法:平时我们如果需要定时地去更新或执行一些操作,我们是通过写crontab去调用php脚本、shell脚本等定时去完成指定操作,例如这样

image.png

但是带来的一个问题就是 当项目比较多的时候,各个项目的定时任务都怼在一起,你很难区分这些定时任务,再者,添加多个定时任务需要你去频繁的利用ssh登录服务器去添加crontab任务,很是让人头疼;而在laravel中 框架就提供了任务调度器去系统且优雅地进行任务调度,我们只需要每分钟去执行框架的

schedule:run

命令即可,它每分钟会去扫描你的定时操作并定期执行,具体调用操作如下

image.png

定义调度

你只需要在app/Console/Kernel的schedule方法中去定义需要执行的操作即可,比如:下面的操作

image.png

你可以像上面的例子一样调用artisancommand去执行操作

也可以去调用像这样的闭包去执行

    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            DB::table('recent_users')->delete();
        })->daily();
    }

亦或者直接用exec去执行系统脚本

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

调用脚本的频次

你可以用如下的框架命令去执行

方法描述
->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();每年运行一次

也可以调用->cron去自定义执行时间(像这样20 0 * * *)

查看任务输出

为了方便查看调度任务的执行结果,平时我们是这样

image.png

去把执行结果在代码中输出 并把输出保存在日志文件中方便查看,laravel中我们可以用sendOutputTo将输出结果保存到指定文件或者用appendOutputTo追加输出结果到指定文件,甚至可以用emailOutputTo发送邮件通知某人执行结果

image.png

任务钩子

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

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


还有像这样的操作

image.png

平时low一点的写法 你完全可以用if else去代替这里的操作,不过框架为我们提供了这样系统且优雅的写法


在框架\vendor\laravel\framework\src\Illuminate\Foundation\Providers\ArtisanServiceProvider.php这个文件中会去注册框架自带的包括schedule:run的commands,

而scheduleRun的具体实现是在\vendor\laravel\framework\src\Illuminate\Console\Scheduling\ScheduleRunCommand.php文件中,是这样的一段代码:


/**
 * Execute the console command.
 *
 * @return void
 */
public function fire()
{
 $eventsRan = false;

 foreach ($this->schedule->dueEvents($this->laravel) as $event) {
 if (! $event->filtersPass($this->laravel)) {
 continue;
 }

 $this->line('<info>Running scheduled command:</info> '.$event->getSummaryForDisplay());

 $event->run($this->laravel);

 $eventsRan = true;
 }

 if (! $eventsRan) {
 $this->info('No scheduled commands are ready to run.');
 }
}

它会获取所有的event 并循环执行,像这样image.png


event类在\vendor\laravel\framework\src\Illuminate\Console\Scheduling\Event.php中

/**
* Run the given event.
*
* @param  \Illuminate\Contracts\Container\Container  $container
* @return void
*/
public function run(Container $container)
{
   if ($this->withoutOverlapping &&
       ! $this->mutex->create($this)) {
       return;
   }

   $this->runInBackground
               ? $this->runCommandInBackground($container)
               : $this->runCommandInForeground($container);
}

这里拿前台执行来说明

/**
* Run the command in the foreground.
*
* @param  \Illuminate\Contracts\Container\Container  $container
* @return void
*/
protected function runCommandInForeground(Container $container)
{
   $this->callBeforeCallbacks($container);

   (new Process(
       $this->buildCommand(), base_path(), null, null, null
   ))->run();

   $this->callAfterCallbacks($container);
}

最后就是拿拼接的参数去组成crontab命令

/**
* Build the command for running the event in the foreground.
*
* @param  \Illuminate\Console\Scheduling\Event  $event
* @return string
*/
protected function buildForegroundCommand(Event $event)
{
   $output = ProcessUtils::escapeArgument($event->output);

   return $this->ensureCorrectUser(
       $event, $event->command.($event->shouldAppendOutput ? ' >> ' : ' > ').$output.' 2>&1'
   );
}

这是buildCommand的结果

image.png

还有一些部分没有介绍,可以参考http://laravelacademy.org/post/9000.html

标签: laravel 任务调度
声明:文章内容由作者原创或整理,转载请标明出处!
暂留位置!--请勿随意修改