laravel定时任务必须由系统cron触发,仅配置schedule方法无效;需在crontab添加cd项目目录后执行php artisan schedule:run的命令,并注意command与call用法区别、时区和环境配置一致性。

schedule:run 不会自动执行,必须由系统级 cron 触发——这是 Laravel 5.5 定时任务能跑起来的唯一前提。
必须在服务器 crontab 里加这一行
不加这行,schedule 方法里写什么都无效。Laravel 调度器只是个“守时员”,它不启动自己。
- 用
crontab -e编辑当前用户的 cron 表 - 添加标准行(路径按你项目实际替换):
* * * * * cd /var/www/myapp && php artisan schedule:run >> /dev/null 2>&1 - 必须用
cd切到项目根目录再执行,否则.env加载失败、autoload 找不到类、配置全错 - 别写成
php /var/www/myapp/artisan schedule:run—— 这种写法绕过工作目录,APP_ENV和timezone极大概率失效
$schedule->command() 和 $schedule->call() 别混用
前者走完整命令生命周期(中间件、日志、DB 事务、异常捕获),后者直接调闭包,没上下文。
- 要发邮件、写
laravel.log、进队列、用DB::transaction()→ 必须用$schedule->command('app:sync-orders') - 用
call()写了事务逻辑,报错也不回滚——因为没经过命令层的 try/catch - 在
call()里调$this->info()没输出——call()根本没有$this实例,更没有输出通道 - 只更新缓存、设标记、调第三方 API 等轻量操作 →
call(function () { cache()->put('last_run', now()); })更合适
时区和环境必须手动对齐
Laravel 调度器只认 config/app.php 里的 'timezone',且必须是 IANA 格式,date_default_timezone_set() 或 APP_TIMEZONE 都不影响它。
- 检查
config/app.php中:'timezone' => 'Asia/Shanghai'(不能写'GMT+8'或'+08:00') - 确认
.env中APP_ENV=production—— 开发环境下schedule:run会静默退出,不报错也不执行 - 临时验证:手动运行
php artisan schedule:run,看终端是否输出Running scheduled command或具体错误
真正容易被忽略的是:调度器本身不感知服务器时间漂移,也不校验 cron 是否真在运行。哪怕 crond 进程挂了、磁盘满导致日志写入失败、或 php 命令路径变了,schedule:run 都不会主动告警——它只负责“该跑的时候跑”,至于跑没跑成,得靠你去查日志、看数据库记录、或加 ->thenPing('@#@#@#@#@#@#@#@#@#@0') 主动上报。











