composer install --dry-run 不报错但实际安装失败,因其仅模拟依赖解析,跳过网络请求、权限校验、脚本执行等真实环节;常见于 CI 误判可行性,上线后因 vendor 权限、install.js 失败或 PHP 扩展缺失而中断。

composer install --dry-run 为什么没报错但实际安装却失败
因为 --dry-run 只模拟依赖解析过程,不真正下载或写入文件,跳过了网络请求、磁盘权限、包完整性校验(如 sha256)、脚本执行(post-install-cmd)等真实环节。常见于 CI 环境中误判“可安装”,结果上线后卡在 file_put_contents(/vendor/autoload.php) 权限错误或某个包的 install.js 脚本失败。
实操建议:
- 把
--dry-run当作“依赖冲突初筛”,而非“安装可行性验证” - CI 中若需预检,应搭配
composer validate+composer show --locked校验 lock 文件一致性 - 遇到
--dry-run成功但install失败,优先检查:/vendor目录权限、composer.json中scripts字段调用的本地命令是否存在、PHP 扩展是否启用(如openssl影响 HTTPS 包下载)
composer update -vvv 输出里哪些行真正关键
-vvv 输出近万行时,90% 是冗余日志。真正要盯住的是三类标记行:
- 以
Reading ./composer.json开头的解析起点 —— 确认读取的是预期文件(尤其多环境共用 repo 时易读错分支下的composer.json) - 含
Resolving dependencies的块 —— 这里会暴露版本约束冲突,例如出现Root composer.json requires laravel/framework ^10.0, found laravel/framework[dev-main, 11.x-dev] but these were not loaded - 末尾的
Writing lock file或Failed to download行 —— 前者说明依赖图已收敛,后者直接指向网络或认证问题(如私有仓库 token 过期)
注意:中间大量 Downloading https://.../package.zip 日志只是进度提示,除非卡住超 2 分钟,否则无需逐行扫。
如何用 -vvv 定位 private repository 认证失败
私有仓库(如 GitLab Package Registry、Satis)认证失败时,-vvv 不会直接报 401 Unauthorized,而是表现为:
- 反复重试同一 URL,最后以
Could not fetch https://.../packages.json, enter your token提示中断 - 或静默跳过该仓库,转而从 packagist.org 回退查找,导致装错包(如装了 public 版本而非 internal 分支)
实操建议:
- 先运行
composer config --global --list | grep github-oauth或对应私仓配置项,确认 token 已写入 - 手动 curl 测试仓库根地址:
curl -H "Authorization: Bearer,验证 token 时效与 scope" https://your.repo.com/api/v4/groups/my-group/projects - 在
composer.json的repositories中显式指定type: "composer"并加options.auth.basic(适用于基础认证),避免依赖全局配置
dry-run 与 -vvv 组合使用的真实场景
线上紧急修复需升级一个 patch 版本,但不确定是否会连带升级其他包破坏兼容性 —— 这时组合用最有效:
composer update monolog/monolog --dry-run -vvv
输出中重点关注:
- 是否出现
Keeping package x/y v1.2.3 (as v1.2.2)类提示 —— 表示版本锁定了,不会动 - 是否有
Downgrading package a/b from v3.0.0 to v2.9.9—— 暗示存在隐式约束冲突,需检查require-dev或未声明的间接依赖 -
Resolving dependencies through SAT后的耗时 —— 若超过 10 秒,说明约束太松,可能触发复杂回溯,应收紧版本号(如改^2.0为~2.3.0)
这个组合不是万能的,它无法反映 autoload 生成后类加载路径变化、PHP 8.2+ 的弃用警告是否被触发 —— 那些得靠实际跑测试用例。










