Laravel的schedule:run必须由系统Cron每分钟触发,因其仅为任务解析器而非守护进程,不监听时钟;无Cron则永不执行。它仅在被调用时比对当前时间与任务频率(如dailyAt('02:00')),决定是否触发,依赖外部轮询驱动。

Laravel 的 schedule:run 不是 Cron 替代品,而是必须依赖系统 Cron 才能工作的解析器;不配系统 crontab,所有调度任务都不会执行。
为什么 schedule:run 必须由系统 Cron 每分钟触发
Laravel Scheduler 本身不是守护进程,也不监听系统时钟。它只在你手动或定时运行 php artisan schedule:run 时,才去 App\Console\Kernel.php 里逐个比对当前时间与每个任务的频率(比如 dailyAt('02:00')),然后决定是否调用对应命令。
这意味着:
- 没有系统级的每分钟 cron 条目,
schedule:run就永远不会被调用,任务永远“躺在代码里” -
schedule:work是可选替代方案,但它需要 Supervisor 或前台进程管理,不是默认路径,也不解决 Docker 无 cron 的问题 - Docker 镜像(如
php:alpine)默认不含crond,crontab -e会直接报错或不可用
crontab 行怎么写才不出权限和路径问题
最简配置 * * * * * cd /var/www/myapp && php artisan schedule:run >> /dev/null 2>&1 在生产环境极易失败,常见卡点:
-
cd后必须是绝对路径;~/myapp或.会因 cron 用户家目录不同而失败 -
php建议写全路径,例如/usr/bin/php,尤其在 cPanel、Plesk 或多 PHP 版本共存环境,否则可能调用错版本或根本找不到命令 - 日志重定向别丢:用
>> /var/www/myapp/storage/logs/schedule.log 2>&1而不是>>/dev/null,否则权限拒绝、.env 加载失败、storage 目录不可写等错误全被吞掉 - cron 运行用户(如
www-data)必须有权限读取.env、写入storage/、执行artisan;部署用root或deploy用户,但 cron 用www-data,就容易因 ownership 不一致导致失败
command() 和 call() 的本质区别不只是“写法不同”
这是执行模型的根本差异,直接影响健壮性和调试成本:
-
$schedule->command('backup:database --gzip'):走完整 Artisan 生命周期,支持参数解析、事件(CommandStarting)、异常捕获、自动服务容器解析;适合涉及 DB、Mail、Queue、文件 IO 的任务 -
$schedule->call(function () { cache()->increment('api_hits'); }):直接执行闭包,跳过中间件、事件、服务注册流程;仅适合纯内存/缓存操作,且你 100% 确保闭包内不依赖未初始化的服务(比如在AppServiceProvider::register()之前就用了DB::connection()) - 闭包里调
dispatch(new SendEmailJob)很危险:Job 序列化后反序列化失败(类名变更、命名空间移动)会静默跳过;command()是字符串调用,更稳定
本地开发时任务总不执行?先查锁、时区、手动触发逻辑
现象是运行 php artisan schedule:run 后没反应,或任务被跳过,常见原因:
- 任务被
withoutOverlapping()锁住:检查storage/framework/cache/data/下是否有残留锁文件(如scheduling-xxx),手动删掉即可 - 服务器时区 ≠ 应用时区:Laravel 默认用
date_default_timezone_set()或config/app.php中的'timezone',但系统 cron 用的是系统时区(timedatectl status查);两者不一致会导致dailyAt('02:00')在错误时间匹配 -
schedule:run只检查“当前分钟是否满足频率”,不回溯也不预跑;比如你在下午 3:05 手动运行,->hourly()任务不会触发(它只在 :00 分触发),->everyFiveMinutes()则会在 :00、:05、:10… 匹配,所以 3:05 刚好命中
真正容易被忽略的是:Laravel 调度器从不“主动等待时间”,它只做一次快照判断;所有“准时”效果,都建立在系统 cron 每分钟雷打不动敲门的基础上——门没敲,它连眼睛都不会睁一下。


















