Laravel 中设置了withoutOverlapping的定时任务失败后,无法重新自动运行的解决方法

    xiaoxiao2025-04-20  7

    问题描述

    在 Laravel 中,想要管理运行 Console/Kernel.php 中的多个计划任务命令,只需开启任务调度器即可。

    开启调度器,只需添加到服务器的 Cron 条目为:

    * * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

    这样,该 Cron 条目每分钟会调用一次 Laravel 的命令调度器,然后,Laravel 会自动评估你的调度任务并自动运行到期的定时任务。

    其中,某条定时任务 A 设置了 withoutOverlapping() 方法,来避免该任务重叠执行。

    如果服务器意外重启或其他情况导致正在运行的任务 A 突然失败,就会导致任务 A 无法重新自动运行。

    你会发现, php artisan schedule:run 调度命令确实在运行,schedule 中其他到期的任务也可以自动执行,唯独任务 A 到期后无法正常运行。

    原因分析

    这和 withoutOverlapping() 方法防止任务重叠执行的机制有关。

    withoutOverlapping() 方法,通过 mutex 互斥文件来防止任务重叠。mutex 互斥标记文件的作用就是标识对应的任务正在执行,从而避免该任务重叠执行。

    由于任务 A 没有正常结束,它对应的 mutex 互斥标记文件就还存在,因此就出现了上述的问题。

    mutex 互斥文件默认存放在 storage/framework 目录中,如:storage/framework/schedule-814aa47847262e468ff17e2978323af621b246c4 文件。

    解决方法

    手动将 mutex 互斥文件删除掉,就能恢复正常。

    rm -f storage/framework/schedule-*

    说明: 本人是在 Laravel 5.2 版本中遇到并解决这个问题的,据说 Laravel 5.4 及以上版本不会出现这种问题(未验证)。

    最新回复(0)