根本原因是composer依赖解析和网络i/o(如github限流、https重试)反复耗时触发php超时,而非单纯执行时间不足;应优先优化网络源、禁用脚本插件、启用离线安装,而非调高max_execution_time。

Composer 安装或更新时卡住并报 Maximum execution time of X seconds exceeded,根本原因不是 PHP 超时本身,而是 Composer 在处理大量包依赖、慢源或网络重试时,反复执行耗时操作(如递归分析、HTTP 请求、JSON 解析)触发了 max_execution_time 限制——直接调高 PHP 超时只是掩耳盗铃,必须从网络、缓存和执行策略三方面入手。
为什么 set_time_limit(0) 或 php.ini 改超时不推荐
Composer 的耗时主要来自外部 I/O:GitHub API 限流、Packagist 响应延迟、HTTPS 握手失败重试、vendor 目录权限校验等。单纯延长 PHP 执行时间会让进程在无响应状态下空转,既不解决问题,又可能阻塞 Web 服务器(尤其在 shared hosting 或 CLI 与 Web 共用 PHP 配置时)。更糟的是,某些托管环境(如 cPanel、Plesk)会强制覆盖 set_time_limit 调用。
-
php -d max_execution_time=0 composer install在 CLI 下看似有效,但若 Composer 内部因 DNS 超时或 SSL handshake hang 住,PHP 进程仍会卡死 - Web 环境下改
max_execution_time几乎无效:Composer 不该在 Web 请求中运行 - 真正瓶颈常是
composer update时的依赖求解(SAT solver),它不耗 CPU,但会因网络抖动反复重试,导致总耗时突破阈值
优先用 --no-scripts 和 --no-plugins 缩短执行链
很多项目在 post-install-cmd 或 post-update-cmd 中绑定了耗时脚本(如生成 autoload、清缓存、运行测试),这些会在 Composer 主流程结束后触发,且默认继承同一超时限制。禁用它们能快速排除干扰项,确认是否真由 Composer 自身逻辑引起。
- 先试
composer install --no-scripts --no-plugins:跳过所有自定义钩子,验证基础安装是否成功 - 若成功,说明问题出在某个
scripts或plugins(比如hirak/prestissimo在旧版 Composer 中有兼容问题) - 再逐个启用:先加回
--no-plugins,看是否稳定;再换用--no-scripts单独测试
换国内镜像 + 关闭 packagist.org 自动 fallback
默认 Composer 源是 packagist.org,国内直连常因 DNS 污染、TLS 握手慢、API 限流(每分钟 60 次)导致请求堆积。即使用了镜像,Composer 默认仍会尝试访问原始源做校验(packagist.org fallback),这一步极易超时。
- 执行
composer config -g repo.packagist composer https://packagist.phpcomposer.com(旧镜像)或composer config -g repo.packagist composer https://packagist.proxy.fly.dev(新可用镜像) - 关键一步:运行
composer config -g repos.packagist false,彻底禁用packagist.org回退机制 - 验证是否生效:
composer config -g repos应只显示你配置的镜像,不含packagist.org - 若仍报超时,检查是否被公司代理或防火墙拦截 HTTPS 请求——可临时加
-vvv看具体卡在哪条GET请求上
终极方案:离线安装 + 依赖锁定
当项目需在受限环境(如内网、CI/CD 无外网权限)部署时,最可靠的方式不是“抗超时”,而是绕过实时解析。核心是利用 composer.lock 和 --no-update 强制跳过依赖分析阶段。
- 在有网机器上确保
composer.lock是最新:运行composer update --lock(仅更新 lock 文件,不下载包) - 把整个
vendor/和composer.lock打包传到目标机,执行composer install --no-interaction --no-progress --no-scripts - 若 vendor 缺失,用
composer install --no-update --no-scripts:它会严格按 lock 文件安装,不做任何远程请求或版本推导 - 注意:
--no-update要求 lock 文件存在且格式合法,否则报Root package 'xxx' cannot be installed because it is not in the lock file
真正难处理的不是超时数字本身,而是 Composer 在网络异常时缺乏明确失败反馈——它会静默重试 5–10 次,每次间隔递增,最终才抛出超时。所以排查时别只盯着 max_execution_time,先用 -vvv 看最后一条日志停在哪,再决定是切镜像、删钩子,还是干脆离线部署。











