Composer install报401时不提示具体原因,因其将HTTP层(packages.json下载)与Git层(git clone)鉴权逻辑分离;需用composer update -vvv定位是HTTP 401(查auth.json的http-basic)还是Git克隆卡住(查HTTPS凭据或SSH密钥),并用composer config --global --list | grep -i auth验证auth.json是否加载。

composer install 报 401 却不提示具体原因
Composer 默认不会区分「token 过期」「权限不足」「域名没配对」,统一抛 401 Unauthorized 或卡在 Cloning into '' 后静默失败。根本原因是它把 HTTP 层(packages.json 下载)和 Git 层(git clone)的鉴权逻辑完全分开处理。
实操建议:
- 先跑
composer update -vvv,看最后几行:若出现Failed to download https://repo.example.com/packages.json (HTTP status 401),说明是 HTTP 鉴权失败,重点查auth.json里的http-basic配置是否匹配仓库域名 - 若卡在
Executing command (CWD): git clone --no-checkout,大概率是 Git 凭据问题:确认私有仓库 URL 是 HTTPS 还是 SSH;HTTPS 依赖系统级凭据(如git config --global credential.helper store)或auth.json中的http-basic生效;SSH 则必须有~/.ssh/id_rsa且已ssh-add - 用
composer config --global --list | grep -i auth快速验证全局auth.json是否加载成功,注意路径是否被COMPOSER_AUTH环境变量覆盖
如何提前验证 token 是否有效
Composer 没有 composer auth:check 命令,但可以用组合命令在 CI 或本地快速暴露问题——关键点在于:Composer 所有流程都始于 GET packages.json,只要这个请求能通,后续基本不会因鉴权中断。
实操建议:
- 对 Packagist 或私有 Satis/SatisPress 仓库:
curl -I -u "token:" https://repo.example.com/packages.json。注意-u "token:"表示用户名为 token、密码为空,这是 OAuth Bearer 的常见模拟方式 - 对 GitHub 私有包:
curl -H "Authorization: token xxx" https://api.github.com/user,检查返回是否含"login"字段;Token 权限需包含read:packages - 对 GitLab 私有包:
curl -H "PRIVATE-TOKEN: xxx" https://gitlab.example.com/api/v4/user,权限需含apiscope - 把这个
curl请求做成 CI 的前置检查项,比等composer install失败再排查快得多
权限不足时 vendor/ 或 composer.lock 写入失败
95% 的 Permission denied 不是权限位(rwx)不够,而是目录属主被 sudo composer install 污染成 root,当前用户无权写入。错误路径就是线索:file_put_contents(/home/alex/myapp/vendor/autoload.php) → 锁定 vendor/;Writing cache file ~/.composer/cache/... → 锁定全局缓存目录。
实操建议:
- 立刻执行三行命令查归属:
ls -ld vendor/、ls -ld composer.lock、ls -ld $(composer config --global cache-dir)。只要任意一行第三列(属主)不是当前用户($(whoami)),就坐实所有权错配 - 修复用
chown,不是chmod:sudo chown -R $USER:$USER vendor/ composer.lock;全局缓存同理:sudo chown -R $USER:$USER $(composer config --global cache-dir) - 禁用
chmod -R 777:它会触发 CI 拒收、Git 提示ownership changed、后续composer update半途失败等连锁反应 - Docker 或 CI 中 UID 不一致?宿主机 UID 是 1001,容器却以 UID 0 运行 → 挂载卷时加
user:1001或 Dockerfile 里加USER 1001
CI/CD 中 auth.json 注入与 working_dir 权限陷阱
GitHub Actions、GitLab CI 等环境里,auth.json 没注入或 working_dir 权限不对,会导致整个流程卡在第一步。Ansible 部署中也常见因 PATH 缺失或 PHP 路径未显式指定而失败。
实操建议:
- GitHub Actions 中,别只靠
actions/checkout,必须显式注入:COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}(内容为 JSON 格式的auth.json字符串) - GitLab CI 中,用
before_script写入:echo "$COMPOSER_AUTH" > ~/.composer/auth.json,并确保该路径对运行用户可写 - Ansible 中优先用
community.general.composer模块,而非 shell 调用:php_executable必须显式指定(如/usr/local/bin/php),working_dir必须指向含composer.json的目录,且对该用户有读写权 - 中文镜像源必须写进
config.json:composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/,命令行参数(如--repository-url)不持久,CI 中无效
sudo composer install 可能让 vendor/ 下混进个别 root 所有子目录,ls -la vendor/ 才能发现。修复必须覆盖整个树,不能只改顶层目录。


















