laravel定时任务不执行绝大多数是系统cron未正确配置,而非代码错误;scheduler仅为时间判断器,必须依赖cron每分钟调用schedule:run才能检查并执行->daily()等任务,否则所有任务仅注册于内存中。

Laravel 的定时任务不执行,绝大多数情况是系统 Cron 没配好,而不是代码写错了。Scheduler 本身不运行后台服务,它只是个“检查表”——必须靠外部每分钟调一次 php artisan schedule:run,它才知道该不该执行你写的 ->daily() 或 ->everyMinute()。
确认系统 Cron 是否已启用并运行
先看 Cron 守护进程有没有在跑:
sudo systemctl status cron # Ubuntu/Debian # 或 sudo systemctl status crond # CentOS/RHEL
如果显示 inactive 或 failed,要先启动:
sudo systemctl start cron sudo systemctl enable cron # 开机自启
检查 crontab 中的调度命令是否正确
运行:
crontab -e
确保里面有一行类似这样(注意全部用绝对路径):
* * * * * /usr/bin/php /var/www/myapp/artisan schedule:run >> /dev/null 2>&1
常见错误点:
- ✅ 用
/usr/bin/php而不是php(别名在 Cron 环境里通常不存在) - ✅
/var/www/myapp/artisan是项目根目录下的artisan文件绝对路径 - ✅ 行尾有换行(最后一行没回车会导致整条失效)
- ✅ 不要在命令前加用户名(如
* * * * * root php ...),除非你是在编辑/etc/crontab
想确认 PHP 路径?运行:
which php
手动触发测试,快速验证逻辑是否通
进项目根目录,直接运行:
php artisan schedule:run
观察输出:
- 如果看到
Running scheduled command: ...,说明注册的任务没问题; - 如果报错(比如
Class not found、Call to undefined method),问题出在命令本身或依赖上; - 如果完全没输出或提示
No scheduled commands are due,说明当前时间不满足你设的触发条件(比如写了->dailyAt('03:00'),但现在是下午)。
加 --verbose 可强制列出所有匹配项:
php artisan schedule:run --verbose
注意时区与环境差异
Laravel 默认用
date_default_timezone_set()设定的时区,但 Cron 运行环境可能用的是系统时区(/etc/timezone或timedatectl查看)。-
推荐统一设为 UTC,或在
config/app.php中显式设置:'timezone' => 'Asia/Shanghai',
-
同时在
app/Console/Kernel.php的schedule方法开头加一行,强制调度器用应用时区:$schedule->useTimezone('Asia/Shanghai');
日志和排错建议
把 Cron 输出重定向到日志文件,比丢进 /dev/null 更利于排查:
* * * * * /usr/bin/php /var/www/myapp/artisan schedule:run >> /var/www/myapp/storage/logs/schedule.log 2>&1
然后实时查看:
tail -f storage/logs/schedule.log
常见报错示例及含义:
-
Permission denied→artisan或storage/目录权限不对(确保 Web 用户和 Cron 用户都有读写权限) -
command not found→ PHP 路径错,或artisan路径错 -
Class 'App\Console\Commands\...' not found→ 命令类没自动加载,运行composer dump-autoload -
proc_open() has been disabled→ PHP 配置禁用了该函数(宝塔等面板常默认禁用,需在php.ini中删掉proc_open)
不复杂但容易忽略











