Laravel Artisan:schedule:run如何工作?

8aqjt8rx  于 2023-03-31  发布在  其他
关注(0)|答案(3)|浏览(210)

我设置了一个虚拟命令作业,其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

==================
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命令是如何确定哪些命令正在“等待”执行的呢?我曾想象会有某种日志文件来记录这样一个事实:“命令X在1小时的时间表上运行,最后一次运行是在09:00,所以不要在10:00之前再次执行它”,但我没有找到这样一个日志的痕迹。
有人能给予我点提示吗?
谢谢!

zxlwwiss

zxlwwiss1#

我知道回答你自己的问题不太好。不管怎样,假设这是我的日程安排:

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

我发现这段代码并没有将作业设置为每5分钟运行一次,也没有阻止在不到5分钟前运行的命令再次运行。
一个更好的思考方法是,这段代码将命名命令 “设置为每当当前时间的分钟数为05 时可运行。换句话说,如果我运行命令行参数:php artisan schedule:run11: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

最后在日志文件中得到输出。
当我的everyFiveMinutes()计划每10分钟在我的文件中创建一个日志时,我发现了上面的问题,因为我的任务计划程序每2分钟运行一次。

wr98u20j

wr98u20j2#

我回答这个问题只是为了让其他人知道(因为我也有同样的困惑)。
Laravel调度程序通过检查任务的cronned时间(以分钟为单位)是否与当前时间完全相同来完成与Linux cron完全相同的工作。
当您在crontab中设置* * * * * ... php artisan schedule:run >> ...时,您将每分钟运行schedule:run 0秒,如'1:00:00','1:01:00','1:02:00'等。
所以,如果你在Laravel调度器中设置命令在“mondays at 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,它将执行N次你计划在1:00运行的任务
这就是不需要表格或文件来控制进程启动时间的神奇之处。分钟是cron的最小单位,所以除非你做错了事情(比如复制schedule:run行,黑客运行命令more often than a minute等),否则你的Laravel任务将在所需的时间执行一次。
只是一个提示:检查你的时区在config/app.php中是否正确。我疯狂地理解为什么像everyMinute(), everyFiveMinutes()这样的东西能工作,而dailyAt('1:10')不能。当然,Laravel在UTC和我在GMT-3(服务器时钟),我在小时上有很大的差异。

eit6fx6z

eit6fx6z3#

现在回答这个问题已经晚了,但我正在为这个问题的解决方案增加一些价值。
我使用了这个命令php artisan schedule:work作为解决方案,这样就不需要每秒钟或每分钟运行一次schedule:run
我希望这将增加问题的价值。

相关问题