我在
Kernel.php
中定义了一个 Laravel 计划作业。
$schedule->call('\App\Http\Controllers\ScheduleController@processQueuedMessages')
->everyFiveMinutes()
->name('process_queued_messages')
->withoutOverlapping();
在开发过程中,我的工作由于语法错误引发了异常。我纠正了错误并尝试再次执行,但还是不行。
我尝试了
artisan down
,然后artisan up
。我还尝试重新启动服务器实例。但没有任何帮助。作业只是没有被执行(也不例外)。
我意识到问题是由于
->withoutOverlapping()
造成的。不知何故,Laravel 调度程序认为该作业已经在运行,并且不会再次执行它。
注意:此解决方案适用于 Laravel 5 Laravel 的后续版本更新了
withoutOverlapping()
功能。请参阅@nmargaritis 的回答。
我通过查看供应商代码找到了解决方案。
Illuminate\Console\Scheduling\CallbackEvent.php
它会在本地存储中创建一个名为
schedule-*
的文件。
public function withoutOverlapping()
{
if ( ! isset($this->description))
{
throw new LogicException(
"A scheduled event name is required to prevent overlapping. Use the 'name' method before 'withoutOverlapping'."
);
}
return $this->skip(function()
{
return file_exists($this->mutexPath());
});
}
protected function mutexPath()
{
return storage_path().'/framework/schedule-'.md5($this->description);
}
删除位于
schedule-*
的文件 storage/framework
解决了问题。
对于阅读本文的任何人来说,自己删除计划文件并不是正确的方法。您需要指定 - 锁定时间 - 在此基础上,withoutOverlapping 会阻止进一步的任务运行。
中所引用如果需要,您可以指定“无重叠”锁定到期之前必须经过多少分钟。默认情况下,锁定将在 24 小时后过期:
您的问题源于 withoutOverlapping 应用了 24 小时的默认锁定。所以你必须等待24小时才能接受类似的任务。只需根据您的需要调整锁定时间即可:
$schedule->command('emails:send')->withoutOverlapping(10); // 其中 10 指分钟
这对我有用:
php artisan cache:clear
我也遇到这个问题了。对此没有适当的解决方案,但解决方法可以解决该问题。
转到项目的存储/框架文件夹并删除所有
schedule-***********
文件。
然后再次尝试运行 cron。即使您使用
withoutOverlapping() function
也会如此。
希望这对您有用。有疑问就问吧。
从 Laravel 8.x 开始,您可以使用特定命令清除互斥文件,例如,如果任务在执行时由于服务器重新启动而卡住
clear:cache
的问题是这个命令清除整个应用程序的缓存,而这个命令只是清除互斥文件
php artisan schedule:clear-cache
这周发生在我们身上,我们认为我们找到了原因。我们的 cron 运行在我们的生产服务器的站点文件夹之一上。我们的部署过程涉及建立第二个文件夹,我们在其中进行部署/构建,然后在最后进行热文件夹交换。由于 withoutOverlapping() 可能需要在进程完成时更新 Schedule-* 文件中的一行,因此文件夹可能会在作业中被交换,并且 cron 无法成功地将作业标记为已在正确的 Schedule-* 文件中完成,所以它认为它仍在运行/卡住。
这种情况很少发生,但我们将添加一个命令来在部署后清除这些文件,这样就不会再发生这种情况。