Laravel定时任务未执行90%是因系统Cron未正确调用schedule:run;调度器仅为时间判断器,非守护进程,必须依赖Cron每分钟触发才能检查并执行任务,否则所有注册任务仅存于内存中。

定时任务没跑,90% 是因为 schedule:run 没被系统 Cron 正确调用,而不是 Laravel 本身有问题。
为什么 schedule:run 必须配系统 Cron
Laravel 的调度器不是后台服务,它只是个「时间判断器」:每分钟检查一遍哪些任务该执行,然后触发对应命令。这个「每分钟检查」的动作必须由外部进程驱动——系统 Cron 就是干这事的。
- 不配 Cron,
schedule:run就永远不会被执行,所有$schedule->command(...)->daily()都只是注册在内存里,不会落地 - 别信“改完
Kernel.php就自动生效”,Laravel 不会自己拉起守护进程 - 常见错误:crontab 里写
php artisan schedule:run却没用绝对路径,导致找不到php或artisan——生产环境必须写全路径,比如/usr/bin/php /var/www/app/artisan schedule:run - 验证是否生效:手动运行
php artisan schedule:run,看输出里有没有 “Running scheduled command” 和你定义的任务名;再查storage/logs/laravel.log是否有对应日志
schedule:work 适合什么场景?
schedule:work 是 Laravel 10.25+ 引入的替代方案,它让调度器自己轮询(毫秒级),不再依赖 Cron 的 1 分钟最小粒度。但它只适合无法控制宿主机 Cron 的环境,比如某些共享主机或容器限制严格的平台。
- 它必须前台持续运行,不能当普通命令用完就退出;一旦进程挂掉,调度就停了——所以必须配 Supervisor 守护
- 和
schedule:run不兼容共存:两个命令都试图触发同一组任务,会导致重复执行 - Docker 中若用
schedule:work,得单独起一个 service,不能和php-fpm或nginx混在同一个容器里,否则容器启动逻辑会冲突 - 注意时区:
schedule:work默认读config/app.php的'timezone',但如果你的容器系统时区没同步(比如没挂载/etc/timezone),时间判断仍会错
Supervisor 配 queue:work 还是 schedule:work?
Supervisor 本质是进程保活工具,它不区分你拉起的是队列还是调度——关键是你配的 command 是什么。
- 如果用
schedule:run(推荐),Supervisor 不需要管它;Cron 调它,它跑完就退出,符合 Unix 哲学 - 如果选
schedule:work,Supervisor 配置里autorestart=true和stopwaitsecs=30必须设好,否则重启部署时旧进程可能卡住不退出,新代码不生效 - 别把
queue:work和schedule:work写进同一个 Supervisor program;它们监听不同信号、处理不同逻辑,混在一起容易互相干扰 - Supervisor 日志(
stdout_logfile)要设成可写路径,且权限属于运行用户(如www-data),否则进程起不来,还查不到原因
多台服务器部署时任务重复怎么办
Laravel 默认不处理分布式锁,withoutOverlapping() 只基于本地文件缓存,跨机器无效。
- 最简方案:所有节点 Cron 都配,但只让其中一台执行关键任务——在
schedule()里加判断:if (app()->environment('production') && config('app.host') === 'scheduler-node-01') { ... } - 更通用做法:用 Redis 实现分布式锁,例如在任务开头写
Cache::lock('backup:database', 3600)->get(...),获取失败就跳过 - 注意:Redis 锁超时时间得比任务预计执行时间长,否则锁提前释放,其他节点可能同时进入
- 别依赖数据库唯一索引做防重——任务刚进队列还没执行,索引拦不住并发触发
真正稳跑的关键不在配置多复杂,而在每次部署后确认三件事:crontab -l 看 Cron 条目是否存在且路径正确、supervisorctl status 看进程是不是 RUNNING、tail -f storage/logs/laravel.log 看最近一两分钟有没有调度日志。漏掉任意一项,都可能静默失效。


















