必须手动验证 ssh 连通性三步:ssh -t git@host 看 hi 用户、ssh-add -l 检密钥加载、git clone 测试静默克隆;任一失败则 composer 必卡在 cloning;ci 中推荐 https + token 替代 ssh。

Composer 本身不处理 SSH 密钥,它只调用 git clone。所谓“注入密钥”,其实是让 Git 在执行克隆时能静默读取并使用你的私钥——只要 git clone git@github.com:org/repo.git 能成功,Composer 就不会卡住。
为什么 composer install 卡在 Cloning into '/tmp/xxx'?
这不是 Composer 报错,而是 Git 在 SSH 认证失败后 fallback 到密码输入,而 Composer 不接管 stdin,直接挂起。常见现象包括:
- 终端光标停住、无输出、无报错
- 日志里出现
Cloning into '/tmp/xxx'后再无下文 - CI 环境中超时退出,错误信息只有
Permission denied (publickey)
根本原因永远是:本地 Git 没法用 SSH 静默连接目标服务器。
验证 SSH 连通性必须手动做三件事
别跳过这步——90% 的失败都卡在这里。依次运行:
-
ssh -T git@github.com(把github.com换成你的真实 Git 域名);必须看到Hi username! You've successfully authenticated -
ssh-add -l;若无输出,说明密钥没加载,执行ssh-add ~/.ssh/id_ed25519(路径按实际调整) -
git clone git@github.com:org/private-repo.git;必须完整拉下代码,中途不能输密码、不能中断
任何一步失败,Composer 都不可能成功。注意:私钥文件权限必须是 600,否则 ssh-add 会静默拒绝加载。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
composer.json 里写 SSH 地址的硬性规则
即使 SSH 连通了,composer.json 写错一个字符也会让 Composer 忽略整个仓库配置:
-
"type"字段必须是"vcs",不是"git"、"package",也不能留空 -
"url"必须是完整 SSH 格式:"git@github.com:org/private-repo.git";冒号分隔,以.git结尾 -
require中的包名(如"org/private-repo")必须和私有库根目录下composer.json中的"name"字段逐字符一致(大小写敏感) - 版本号不能写
"*"或省略,得显式写"dev-main"、"1.0.0"等可解析的引用
如果用了自定义域名(如 git.internal),~/.ssh/config 中的 Host 条目必须和 URL 里的 host 完全一致,且含 User git 和 IdentityFile。
CI 环境下别硬扛 SSH,优先换 HTTPS + token
GitHub Actions、GitLab CI 等环境默认没有交互式 ssh-agent,ssh-add 容易因换行符(\r\n)或权限问题静默失败。更稳的做法是:
- 生成只读 Personal Access Token(GitHub)或 Project Access Token(GitLab),赋予
read_package_registry权限 - 在
composer.json中改用 HTTPS URL:"https://token:x-oauth-basic@github.com/org/private-repo.git" - 或通过
COMPOSER_AUTH环境变量注入 JSON:{"github-oauth": {"github.com": "${GITHUB_TOKEN}"}}
这样绕开 SSH 配置的全部复杂性,也避免了 ~/.ssh/config 全局污染和密钥格式兼容问题。
最常被忽略的点:PHP 进程用户(比如 www-data)和你当前终端用户不是同一个,它的 ~/.ssh 目录可能为空,ssh-agent 也未启动——此时就算你在自己账户下配好了,Web 请求依然会失败。










