我有一个虚拟命令作业,其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" 之前,但我找不到这样的日志痕迹。
有人能给我一些线索吗?
谢谢!
答案 0 :(得分:2)
我知道,回答你自己的问题并不酷。无论如何,让我们想象这是我的日程安排:
protected function schedule(Schedule $schedule)
{
$schedule
-> command('cbh:dummyCommand')
-> everyFiveMinutes()
-> appendOutputTo ('/my/logs/laravel_output.log');
}
我发现的是,此代码并未将您的工作设置为每5分钟运行一次。如果命令运行时间不到5分钟,它也不会阻止命令再次运行。
考虑它的一个更好的方法是,每当当前时间的分钟数为0
或5
时,此代码将命名命令"设置为可运行" 。换句话说,如果我在php artisan schedule:run
运行命令行参数:11:04
,则响应为:
# No scheduled commands are ready to run.
但如果我在11:00
或11: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(服务器时钟)的情况下,我在小时数上有很大差异。