Laravel Artisan:如何安排:跑步?工作?

时间:2018-02-08 11:26:00

标签: laravel laravel-5 artisan

我有一个虚拟命令作业,其handle()功能如下:

public function handle()
{
    $this->line('==================');
    $this->line('Running my job at ' . Carbon::now());
    $this->line('Ending my job at ' . Carbon::now());
}

如您所见,除了向标准输出返回几行信息之外,它实际上并没有做任何事情。

现在,在我的App\Console\Kernel课程中,我设置了以下时间表:

protected function schedule(Schedule $schedule)
{
    $schedule
        -> command('cbh:dummyCommand')
        -> everyMinute()
        -> appendOutputTo (storage_path().'/logs/laravel_output.log');
}

现在,从命令行运行php artisan schedule:run。我的laravel_output.log文件中的输出读取

==================
Running my job at 2018-02-08 11:01:33
Ending my job at 2018-02-08 11:01:33

到目前为止一切顺利。好像我的日程表正在运行。但是,如果我在同一分钟内再次运行该命令,我的日志文件现在显示为:

==================
Running my job at 2018-02-08 11:01:33
Ending my job at 2018-02-08 11:01:33
==================
Running my job at 2018-02-08 11:01:51
Ending my job at 2018-02-08 11:01:51

换句话说,时间表似乎比每分钟更频繁地运行,这在我看来违反了我在日程表中定义的规则。

更令人困惑的是,我可以将计划更改为每5分钟而不是每分钟运行一次:

protected function schedule(Schedule $schedule)
{
    $schedule
        -> command('cbh:dummyCommand')
        -> everyFiveMinutes()
        -> appendOutputTo (storage_path().'/logs/laravel_output.log');
}

然后运行php artisan schedule:run,然后我得到以下输出

  

没有预定的命令可以运行。

我可以等到你喜欢的时间(即超过5分钟)但仍然没有输出到我的日志文件。

当我使用Windows任务计划程序安排命令时,我观察到完全相同的行为(是的,我的开发环境是Windows 7框,是的,这是Windows等效的cron-job)。

问题

那是怎么回事? artisan schedule:run命令如何确定哪些命令是"等待"按计划执行?我曾经想过会有某种日志文件来记录" Command X是1小时的时间表,最后一次是在09:00运行,所以不要执行它再次在10:00" 之前,但我找不到这样的日志痕迹。

有人能给我一些线索吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

我知道,回答你自己的问题并不酷。无论如何,让我们想象这是我的日程安排:

protected function schedule(Schedule $schedule)
{
    $schedule
        -> command('cbh:dummyCommand')
        -> everyFiveMinutes()
        -> appendOutputTo ('/my/logs/laravel_output.log');
}

我发现的是,此代码并未将您的工作设置为每5分钟运行一次。如果命令运行时间不到5分钟,它也不会阻止命令再次运行。

考虑它的一个更好的方法是,每当当前时间的分钟数为05时,此代码将命名命令"设置为可运行" 。换句话说,如果我在php artisan schedule:run运行命令行参数:11:04,则响应为:

# No scheduled commands are ready to run.

但如果我在11:0011:05运行相同的命令,那么我们会得到:

# Running scheduled command: php artisan cbh:dummyCommand >> /my/logs/laravel_output.log 2>&1

我最终得到了我的日志文件中的输出。

根据我的任务调度程序每2分钟运行一次的事实,我的everyFiveMinutes()计划每10分钟在我的文件中创建一个日志时发现了上述内容。

答案 1 :(得分:1)

我回答这个问题只是为了让其他人知道(因为我有同样的困惑)。

Laravel调度程序通过检查任务完成时间(以分钟为单位)是否与当前时间完全相同,来完成与Linux cron完全相同的工作。

在crontab * * * * * ... php artisan schedule:run >> ...中进行设置时,您每隔0秒就会运行schedule:run,例如“ 1:00:00”,“ 1:01:00”,“ 1:02:00” ',等等。

因此,如果您将命令设置为在Laravel调度程序的“周一1:00”运行(例如),而您在周一的1:00运行,则当前秒数。最后一部分()对于理解其工作原理很重要。

例如,您在星期一的1:00:05(1:00之后的5秒),因此cron已启动schedule:run,并且您的任务正在执行。然后打开终端,转到项目的根目录,然后手动启动php artisan schedule:run。那时可能是1:00:30(1:00后30秒)。好了,现在您的任务将再次执行,因为1:00:30仍然是1:00的一部分。因此,您可以在1:00执行N次schedule:run,它将在您计划在1:00运行的任务中执行N次。

这就是不需要表或文件来控制进程启动时间的魔力。分钟是cron中的最小单位,因此,除非您做错了事情(例如复制schedule:run行,运行命令more often than a minute的黑客程序等),您的Laravel任务将在所需时间。

请注意:在config/app.php中检查您的时区是否正确。我很疯狂地了解为什么everyMinute(), everyFiveMinutes()之类的东西为什么有效,而dailyAt('1:10')之类的东西却无效。当然,在UTC的Laravel和我在GMT-3(服务器时钟)的情况下,我在小时数上有很大差异。