Laravel调度器需系统cron触发,因本身非守护进程;须配置绝对路径的crontab条目,注意时区、用户权限、PHP路径及环境变量隔离。

为什么 php artisan schedule:run 在服务器上不自动执行
因为 Laravel 的调度器本身不是守护进程,它只负责定义任务逻辑,不负责触发——真正触发得靠系统级的 cron。部署后如果没配系统 cron,schedule:run 就永远不会被调用。
常见错误现象:php artisan schedule:run 手动执行时任务正常,但到点不跑;日志里看不到调度记录;storage/logs/laravel.log 里也没有 Scheduled command 相关输出。
- 必须在服务器上添加一条系统
cron条目,指向 Laravel 的调度命令 - 推荐用
crontab -e添加:* * * * * cd /var/www/your-app && php artisan schedule:run >> /dev/null 2>&1 - 路径必须写绝对路径,
cd切到项目根目录是必须的,否则artisan找不到配置和自动加载 - PHP 可执行文件要用
which php确认,有些服务器(如 CentOS)默认php命令可能指向旧版本或 CLI 不一致
Laravel schedulable 任务里不能用 $this->call() 吗
能用,但非常容易出错——$this->call() 是用于从一个 Artisan 命令里调用另一个命令,而调度任务本身是 Schedule 对象注册的闭包或命令类,不在 Artisan 命令上下文中。
使用场景:你想在定时任务里触发另一个命令(比如清理缓存),但又不想单独写个新命令类。
- 正确做法是直接用
Artisan::call('cache:clear'),需先use Illuminate\Support\Facades\Artisan; -
$this->call()只在继承Command的类内部有效,比如你在app/Console/Commands/MyTask.php里写,才可以用 - 如果在
app/Console/Kernel.php的schedule()方法里写闭包,$this指向的是Kernel实例,没有call()方法,会报Call to undefined method ...call() - 性能影响不大,但混用命令调用方式会让调试路径变长,建议统一用
Artisan::call()或封装为独立命令类
线上环境 APP_ENV=production 下任务不执行怎么办
不是 Laravel 阻止了,而是默认配置下,schedule:run 会在非本地环境跳过「测试模式」检查,但如果你手动加了 ->when() 或用了 env() 判断,就可能误判。
常见错误现象:本地 APP_ENV=local 一切正常,上线后 APP_ENV=production,日志里完全没调度痕迹,甚至 schedule:run 手动执行也返回空响应。
- 检查
app/Console/Kernel.php中是否写了类似->when(fn() => app()->environment('local')),这会让任务只在本地运行 -
APP_DEBUG=false不影响调度,但会影响错误是否写入日志,建议线上开启LOG_LEVEL=debug临时排查 - 确认
config/app.php的timezone和服务器系统时区一致,否则任务时间对不上(比如服务器是 UTC,Laravel 设成 Asia/Shanghai,就可能差 8 小时) - 某些共享主机或容器环境禁用了
exec(),会导致Artisan::call()失败且静默,可在任务里加Log::info('before call');和Log::info('after call');定位卡点
多个 Laravel 应用共用一台服务器时 crontab 怎么隔离
不能共用同一行 cron 调度所有项目,否则路径、环境变量、PHP 版本、用户权限全乱套。
使用场景:你有 blog.test、api.example.com 两个 Laravel 项目部署在同一台 VPS 上。
- 每个项目必须用独立的
crontab -u www-data -e(或对应 Web 用户),避免权限冲突 - 每条
cron必须带完整路径:* * * * * cd /var/www/blog && /usr/bin/php artisan schedule:run >> /var/www/blog/storage/logs/schedule.log 2>&1 - 日志路径也要分开,别都往
/var/log/syslog里塞,否则查问题时分不清是谁的日志 - 如果用 Supervisor 管理队列,注意
queue:work和schedule:run是两回事——前者处理队列任务,后者只是“触发”调度,别把它们当成同一个东西去配
最常被忽略的是时区和用户权限:cron 默认用 root 或当前用户执行,而 Web 请求是 www-data 或 nginx 用户,文件写权限、.env 加载、日志路径可写性,三者缺一不可。











