应同时调高http.timeout(控制HTTP全周期,开发机600秒、CI/CD 1200~1800秒)和process-timeout(控制git clone/unzip等子进程,同级建议值),并确保PHP default_socket_timeout不小于二者,否则底层提前中断。

没有统一“合适”的秒数,只看你的环境和用途——开发机设600秒够用,CI/CD建议1200~1800秒,但必须同步调高http.timeout和process-timeout,缺一不可。
卡在Downloading https:// 时该调 http.timeout
这是单次 HTTP 请求卡住,比如拉 packages.json 或下载 ZIP 包,错误里常带 cURL error 28 或反复 retry。它完全不看 process-timeout,只认 http.timeout(Composer 2.x)或 http-basic-timeout(2.2+)。
- 默认值太激进:旧版
http.timeout默认 300 秒,2.2+ 的http-basic-timeout默认仅 60 秒,国内首字节延迟高时极易触发 - 推荐值:开发机设
600,CI/CD 设1200;命令行临时覆盖用COMPOSER_HTTP_TIMEOUT=1200或--http-basic-timeout=300 - 关键前提:PHP CLI 的
default_socket_timeout必须 ≥ 你设的http.timeout,否则底层直接掐断——运行php -i | grep default_socket_timeout查,常见默认值是 60,得先改它
卡在 Executing command (git clone / unzip) 时该调 process-timeout
错误信息明确含 The process "" exceeded the timeout,加 -vvv 能看到最后执行的那条命令。这和 HTTP 下载无关,是子进程(如 git clone、解压、运行 post-install-cmd)超时被杀。
- 默认 300 秒在私有 GitLab、大体积包(如
laravel/sail)、CI 带宽受限场景下根本不够 - 开发机建议设为
600,CI/CD 建议1200~1800;禁用超时(设为0)不推荐,可能无限挂起 - 项目级写进
composer.json的config段最稳:"process-timeout": 1200;全局生效用composer config -g process-timeout 1800 - 环境变量
COMPOSER_PROCESS_TIMEOUT优先级最高,适合 Docker 或 GitHub Actions 中兜底
只改一个 timeout 为什么还会失败
因为 http.timeout 和 process-timeout 管的是完全不同的阶段,互不替代。只调高其中一个,大概率仍失败。
-
http.timeout控制「每个 HTTP 请求」:DNS + TLS + 首字节 + 整个 body 传输,比如下载一个 100MB 的 ZIP -
process-timeout控制「整个命令生命周期」:依赖解析 + 多轮 HTTP 下载 + 解压 + 运行脚本 + 生成 autoload,哪怕每个 HTTP 都没超时,总耗时也可能爆掉 - 典型失败链:HTTP 请求设了 1200 秒,但
process-timeout还是 300 秒 → 下完包刚准备解压就被 kill - 临时命令要两个都带:
composer install --timeout=1200 --http-basic-timeout=300
比调 timeout 更有效的三件事
单纯拉长 timeout 是“等得更久”,不是“更快完成”。真正省时间、少失败的做法是:
- 换国内镜像源:
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/,配完立刻composer clear-cache - 关掉 packagist.org 回源:镜像配置后若仍慢,检查是否启用了
packagist.orgfallback,关掉能避免 DNS 污染和 TLS 抖动 - 精准清理中断残留:
rm -f vendor/autoload.php && rm -rf vendor/composer/,再composer dump-autoload→composer install;别直接删整个vendor/,否则后续命令会因缺失autoload.php报错
最容易被忽略的是 PHP 底层的 default_socket_timeout —— 它像一道闸门,不管你 Composer 配多大,它一关,cURL 就提前报错,Composer 根本收不到你设的值。











