laravel生产环境定时任务稳定执行需三步:一、确保app_env=production且kernel.php中正确注册schedule()任务;二、用绝对路径配置系统cron每分钟调用schedule:run并切换至项目根目录;三、验证时区为iana格式(如asia/shanghai)、权限正确、日志可查。

在Laravel生产环境中让定时任务稳定执行,必须确保系统级Cron每分钟准确调用schedule:run,且APP_ENV=production、路径权限、时区全部匹配,否则任务会静默失效。
确认Laravel调度逻辑已注册
打开app/Console/Kernel.php,检查schedule()方法中是否已添加任务注册语句。漏掉这一步,后续所有配置都无效。
例如:$schedule->command('backup:database')->dailyAt('03:00'); 或 $schedule->call(function () { \Log::info('cron ping'); })->everyMinute();
运行php artisan schedule:list,能列出任务才说明注册成功;若报错或为空,返回检查Kernel.php语法和命令类是否存在。
强制设置生产环境变量
编辑项目根目录下的.env文件,将APP_ENV明确设为production:
【APP_ENV=production】
Laravel在非production环境下会直接跳过整个调度流程——哪怕你手动运行php artisan schedule:run也不会触发任何任务,且不报错、无日志。
同时确认APP_DEBUG=false,避免敏感信息泄露;若调试阶段需日志,临时设为true,上线前必须改回false。
配置Linux服务器Cron条目
以项目实际运行用户(如www-data)身份执行:
第一步:sudo -u www-data crontab -e
第二步:在打开的编辑器中添加这一行(路径按你服务器实际情况替换):
* * * * * cd /var/www/myapp && /usr/bin/php artisan schedule:run >> /dev/null 2>&1
注意:必须用绝对路径调用php,不能写php——生产环境常未将PHP加入PATH,或PATH指向错误版本;必须cd切换到项目根目录,否则artisan无法加载.env和autoload,会报“Class not found”或数据库连接失败。
保存退出后,执行sudo systemctl restart cron(Ubuntu/Debian)或sudo systemctl restart crond(CentOS/RHEL)使配置生效。
验证任务是否真正运行
方法一:手动触发并观察输出
进入项目根目录,执行php artisan schedule:run,终端应显示“Running scheduled command: …”及对应命令输出。若只显示“No scheduled commands are ready to run.”,说明当前时间不匹配任务设定频率,或APP_ENV仍为local。
方法二:查看Laravel日志
检查storage/logs/laravel.log,搜索“Scheduled command”关键词,确认有带时间戳的记录。
方法三:加一行测试日志到任务里
在Kernel.php中临时添加:$schedule->call(function () { \Log::info('CRON-TEST-'.now()); })->everyMinute();,等两分钟后查log,有连续时间戳即通。
修复常见失败原因
如果任务仍不执行,按顺序排查以下三项:
① 执行crontab -l -u www-data,确认刚添加的那行Cron存在且无拼写错误;
② 进入项目目录,执行ls -l artisan,确认文件权限为644或755,且属主是www-data;
③ 检查config/app.php中的'timezone' => 'Asia/Shanghai',必须是IANA格式,不能写'GMT+8'或'UTC+8'——否则dailyAt('03:00')会按服务器本地时间而非业务时间触发。











