Composer在非交互终端卡住等密码输入,根本原因是默认启用交互模式且未预置私有仓库凭证,需加--no-interaction并提前配置auth.json或环境变量凭证,同时确认SSH/HTTPS协议未意外切换。

Composer在非交互终端里卡住等密码输入
这是最常见的情况:你在 CI/CD 环境、Docker 构建、SSH 非登录 Shell 或重定向了 stdin 的脚本中运行 composer install,Composer 检测到需要认证(比如私有包仓库),试图读取密码,但 stdin 不可交互,于是进程挂起、光标不动、无报错也无响应。
根本原因不是“密码输不了”,而是 Composer 默认启用交互模式(--no-interaction 未显式关闭),而底层 PHP 的 stream_get_line(STDIN, ...) 在非 TTY 环境下直接返回 false,Composer 却没及时 fallback 或报错。
- 确认是否真在非 TTY 环境:
php -r "var_dump(stream_isatty(STDIN));"返回bool(false)就是 - 临时绕过:加
--no-interaction参数(但需提前配置好凭证,否则会失败) - 不要用
echo "xxx" | composer install—— 密码不会被识别,Composer 不从管道读密码
私有仓库认证凭据没预置,又没关交互
当你配置了 repositories 指向需 Basic Auth 的私仓(如 GitLab Package Registry、自建 Satis),但没在 auth.json 里写入对应 http-basic 凭据,Composer 就会在安装时尝试交互式索要用户名和密码 —— 此时若终端不可交互,就卡死。
- 正确做法:把凭证写进项目根目录的
auth.json(注意权限:chmod 600 auth.json) - 示例内容:
{ "http-basic": { "gitlab.example.com": { "username": "token", "password": "glpat-xxxxxx" } } } - 也可用环境变量注入:
COMPOSER_AUTH='{"http-basic":{...}}' composer install,适合 CI - 避免用
composer config写全局auth.json,容易泄露凭证
Git SSH 密钥未加载或代理失效导致回退到密码提示
如果 Composer 依赖的包源是 Git URL(如 "git@gitlab.com:org/pkg.git"),但 SSH agent 未运行、密钥未添加、或 ~/.ssh/config 中 Host 别名没配好,Composer 可能悄悄降级尝试 HTTPS 协议,再触发 HTTP Basic 认证流程 —— 这时候你根本没意识到它已切协议,还在等 Git 的 SSH 密码(其实 SSH 不弹密码,是 HTTPS 在弹)。
- 检查实际走的协议:
composer install -v看日志里 clone 用的是git@...还是https://... - 强制走 SSH:
"url": "git@gitlab.com:org/pkg.git"+ 确保ssh -T git@gitlab.com能通 - 禁用 HTTPS 回退:在
config中设"github-protocols": ["ssh"](对 GitHub 有效),其他平台需靠仓库 URL 显式指定协议
某些旧版 Composer(2.2.0 早期)存在 stdin 检测 bug
部分版本在 Docker 容器或 systemd service 中,即使加了 --no-interaction,仍因 stream_isatty() 判断失准而误入交互分支。这不是你配置错,是 Composer 自身逻辑缺陷。
- 验证版本:
composer --version;优先升级到2.5.8+或2.4.4+(修复较全) - 临时 workaround:
script -qec "composer install --no-interaction" /dev/null(伪造 TTY) - 更稳做法:CI 中统一用
COMPOSER_NO_INTERACTION=1环境变量,比参数更早生效
真正卡住时,别急着查密码格式或网络——先确认 stdin 是否可用、凭证是否预埋、协议是否意外切换。这三个点覆盖了 90% 的“能看不能输”场景。剩下的是版本 bug,得换版本或绕过。











