opcache对laravel cli脚本(如队列worker、artisan命令)默认不生效,因php cli与fpm配置独立,需显式设opcache.enable_cli=1并调优;否则每次执行均重新编译,且须配合opcache.dups_fix=1防类重复声明、重启进程而非opcache_reset()清缓存。

OPcache 对 Laravel 并发脚本(如队列 worker、定时任务、Artisan 命令)的加速效果有限,甚至默认不生效——因为 PHP CLI 模式下 OPcache 默认关闭,且预加载(preload)在 CLI 中不可用。想让 php artisan queue:work 或 php artisan schedule:run 真正变快,必须显式启用并调优 CLI 环境的 OPcache。
为什么 CLI 脚本默认不走 OPcache?
PHP 的 Web(FPM/Apache)和 CLI 是两套独立的 SAPI,opcache.enable=1 只影响 Web 请求;CLI 下即使扩展已加载,opcache.enable_cli 默认为 0。运行 php -i | grep opcache.enabled 很可能返回 opcache.enabled => Off,这就意味着每次执行 Artisan 命令都要重新解析、编译全部框架和业务文件。
-
opcache.enable_cli=1必须显式写入 CLI 使用的 php.ini(常位于/etc/php/*/cli/php.ini或$(php --ini | grep "Loaded" | awk -F': ' '{print $2}')/cli/php.ini) - 仅改 FPM 的 php.ini 不影响
php artisan命令 - 宝塔用户注意:PHP 设置页中“配置修改”默认只改 FPM 配置,CLI 配置需单独编辑对应路径下的 cli/php.ini
CLI 下如何安全启用 OPcache 并避免类冲突?
开启 opcache.enable_cli=1 后,php artisan opcache:compile 才能真正编译 CLI 环境下的字节码。但直接运行会报 Fatal error: Cannot declare class XXX, because the name is already in use —— 这是因为 Laravel 的自动加载机制在 CLI 中多次 require 同一文件(尤其在循环执行的 worker 中),而 OPcache 默认禁止重复声明。
- 必须设置
opcache.dups_fix=1(推荐加到 CLI 和 FPM 的 php.ini 共同区段) - 若无法改 ini(如共享主机),改用
php artisan opcache:compile --force绕过检查,但仅限部署阶段,勿用于持续运行的 worker -
opcache.validate_timestamps=0在 CLI 下可设为 0(无热更新需求),但务必配合部署流程:先php artisan opcache:clear,再启动新 worker 进程 - 别依赖
opcache_reset()清 CLI 缓存——它只清当前进程的缓存,对已 fork 的 worker 无效;重启 worker 进程才是唯一可靠方式
队列 worker 性能瓶颈真在 OPcache 吗?
多数 Laravel 队列慢的根源不在字节码编译,而在反复加载配置、服务提供者、环境变量。OPcache 编译只能省掉「编译」时间(毫秒级),但无法跳过「注册服务容器绑定」「解析 .env」「加载 config/*.php」这些耗时操作。实测显示:对单次短任务(queue:work --daemon,收益更小,因首次加载后后续任务复用内存结构。
- 优先做
php artisan config:cache和php artisan route:cache(确认无闭包路由) - 禁用开发扩展:确保 CLI 环境下
xdebug.enable=0、blackfire.enable=0,它们会让 OPcache 几乎失效 - 避免在
AppServiceProvider::boot()中做 I/O 操作(如读文件、查 DB),这类逻辑无法被 OPcache 加速 - 真正的并发提升来自横向扩 worker 进程数 + Redis 队列分片,而非单个进程的 OPcache 微优化
CLI OPcache 是个「锦上添花」项,不是「雪中送炭」方案。它只在高频调用短生命周期命令(如每分钟跑一次的 schedule:run)时有明显价值;对长期驻留的 queue:work,更应关注内存泄漏、数据库连接复用、日志刷盘频率等底层问题。











