设了http.timeout仍卡在cURL error 28,是因为底层PHP default_socket_timeout默认60秒会强制中断,Composer根本收不到上层配置;需同步调高default_socket_timeout至≥http.timeout值。

Composer 本身不支持“长连接保持”,它用的是短连接 + 重试机制;所谓“不中断”,其实是调高超时阈值、同步调整 PHP 底层 socket 限制、并禁用可能提前掐断连接的环节。
为什么设了 http.timeout 还是卡在 cURL error 28?
因为 Composer 的 http.timeout 只是上层逻辑控制,底层仍走 PHP 的 default_socket_timeout。如果这个值是默认的 60 秒,哪怕你把 http.timeout 设成 1200,cURL 在第 61 秒就会直接报 cURL error 28,Composer 根本收不到你的配置。
- 查当前值:
php -i | grep default_socket_timeout - 临时改(CLI 模式):
php -d default_socket_timeout=1200 composer install - 永久改:编辑
php.ini中的default_socket_timeout = 1200,然后重启 CLI 环境(Docker 容器需重建) - 注意:该设置只影响 PHP 的 stream context,不影响
proc_open()子进程(如 git clone),那是process-timeout管的
process-timeout 和 http.timeout 到底谁管什么?
这两个配置完全独立,分别控制不同阶段:
-
process-timeout:控制每个外部命令(git clone、unzip、post-install-cmd脚本)的最大执行时间,默认 300 秒;错误里一定含The process "" exceeded the timeout -
http.timeout:控制单次 HTTP 请求总耗时(DNS + TLS + 首字节 + body 下载),默认 300 秒;卡在Downloading https://...时调它 - Composer 2.2+ 新增
http-basic-timeout,更细粒度控制基础 HTTP 连接/读取,但旧版本不认 - 三者可共存:比如
COMPOSER_PROCESS_TIMEOUT=1200 COMPOSER_HTTP_TIMEOUT=900 COMPOSER_HTTP_BASIC_TIMEOUT=300 composer install
CI/CD 或 Docker 中最容易漏掉的三个点
环境隔离导致配置失效,不是没设,而是没生效:
- 未显式挂载或设置
COMPOSER_HOME,容器重启后composer config -g写的全局配置丢失 - Docker 执行时被外层
timeout命令包裹(如timeout 600 composer install),系统级中断优先于 Composer 超时,错误日志里看不到ProcessTimedOutException,只有signal: killed - GitHub Actions 默认 runner 的 PHP
max_execution_time是 30 秒,而 Composer 脚本(如post-install-cmd)由 PHP 直接执行,必须用php -d max_execution_time=0显式覆盖
真正决定“是否中断”的从来不是 Composer 自己,而是 PHP 的 socket 层、系统 timeout、以及子进程调度器。调高 timeout 参数只是让失败来得晚一点,而不是让连接变“长”。











