Composer默认process-timeout为300秒,是早期小项目场景的保守设定;如今面对复杂依赖、国内网络延迟、CI资源限制等,该值常导致git clone或unzip超时失败,需同步调高process-timeout、http.timeout和http-basic-timeout,并检查PHP底层socket超时配置。

Composer 默认 process-timeout 设为 300 秒(5 分钟),不是拍脑袋定的,而是权衡本地开发机性能、常见依赖规模和网络响应后的保守起点——它够跑通小项目、单机调试、干净镜像下的标准流程,但对真实复杂场景(尤其国内网络、私有仓库、CI 环境)完全不够用。
为什么300秒在今天基本等于“必超时”
这个值诞生于 Composer 1.x 时代,当时主流项目依赖少、dist 包小、多数开发者直连 packagist.org。现在常见情况已完全不同:
- 一个 Laravel + Vue + 多个私有 SDK 的项目,
composer update要解析数百个包、触发数十次git clone或 ZIP 下载,单个unzip或git checkout就可能卡 60 秒以上 - 国内用户走阿里云/腾讯云镜像,DNS 解析+TLS 握手+首字节等待常占 2–5 秒,叠加 50+ 包下载,光 HTTP 层就轻松突破 300 秒
- CI 环境(如 GitHub Actions)默认资源受限,Docker 容器内存不足时,
unzip或composer install的 PHP 进程会变慢,但 Composer 不感知内存压力,只看时间
process-timeout 和 http.timeout 完全不是一回事
很多人改了 config.timeout 或 http-basic-timeout 发现没用,就是因为混淆了作用域:
-
process-timeout控制每个外部命令(git clone、unzip、post-install-cmd脚本)的最大执行时间,单位秒,默认 300 -
http.timeout控制单次 HTTP 请求从 DNS 开始到 body 传输完成的总耗时,默认也是 300,但只影响file_get_contents()或 cURL 拉取packages.json或 ZIP 包 -
http-basic-timeout(Composer 2.2+)更细粒度,只管连接建立和首字节等待,默认仅 60 秒,大包下载时极易先卡在这一步
错误日志里出现 The process "git clone ..." exceeded the timeout,一定是 process-timeout 在起作用;出现 cURL error 28 或反复 retry,则是 http.timeout 或 http-basic-timeout 先扛不住。
设太高或设太低都埋雷
盲目拉高 timeout 值不解决问题,反而掩盖真正故障:
- 设成
0(不限时):一旦遇到权限错误、磁盘满、Git 凭据失效,进程会永远卡住,CI 流水线挂死,没人能发现 - 只调
process-timeout却忽略php.ini的default_socket_timeout:后者若仍是 60 秒,HTTP 层会在 Composer 的http.timeout触发前就被 PHP 强行中断 - 在
composer.json里写"timeout": 1200:这个字段根本不存在于 Composer 配置规范中,会被静默忽略
真正要调的只有三个地方:process-timeout(子进程)、http.timeout(HTTP 总耗时)、http-basic-timeout(单次请求握手),且必须同步检查 PHP 底层 socket 超时——漏掉任意一环,timeout 设置就形同虚设。











