必须用flock串行化操作,且锁对象只能是已存在并可写的composer.lock;若文件不存在则flock立即失败,应先从main分支检出该文件,或改锁.git目录以提升鲁棒性。

CI/CD中多个job并发执行composer install时卡死,根本不是网络或镜像问题,而是composer.lock被多个进程同时读写导致的竞争条件——必须用flock串行化,且锁对象只能是composer.lock本身。
为什么flock ./composer.lock -c 'composer install'会失败
常见错误是直接对不存在的composer.lock加锁。Linux/macOS下flock要求目标文件已存在、可写,否则命令立即退出并返回非零码,后续composer install根本不会执行。
- 新分支首次构建、或
git clean -fdx后,composer.lock可能被清空 - 此时应先确保它存在:比如从
main分支git checkout main -- composer.lock再加锁 - 不能用
flock ./composer.json——它只读不写,锁无效;也不能锁vendor/目录,composer install不直接写该目录(而是写入子目录)
composer install在CI里卡在“Resolving dependencies…”的真实原因
这不是求解器真在“计算”,而是因PHP平台不匹配触发了无限回溯:比如composer.json写"php": "^8.2",但CI job跑在PHP 8.0上,Composer不敢报错,转而尝试降级所有包来凑出兼容组合,最终超时。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 现象:日志停在
Resolving dependencies...超过2分钟,无任何错误输出 - 验证方式:
php -v和composer show --platform对比PHP版本是否一致 - 禁用
--ignore-platform-reqs——它只是把问题往后拖,运行时仍会Fatal error
GitLab CI中避免多job并发冲突的稳妥做法
锁单个文件风险高,更推荐锁整个工作区。GitLab Runner默认共享.git/目录,且它始终存在、可写,是天然的锁载体。
- 正确写法:
flock .git -c 'composer install --no-interaction --prefer-dist' - 比锁
composer.lock更鲁棒:即使lock文件被删,锁依然生效 - 配合
COMPOSER_MEMORY_LIMIT=-1防OOM,否则flock成功但composer install中途被kill,锁自动释放,下一个job又撞进来
自动化流程里混用composer update是致命错误
截至2026年7月,composer update仍无任何并发保护机制。一旦两个PR几乎同时触发CI,各自重写composer.lock,谁最后写完谁赢,中间人的修改静默丢失——线上部署时composer.lock哈希与任一PR都不匹配,一致性彻底崩溃。
- CI/CD中必须拆开两步:
composer update仅限人工触发、本地执行;CI只跑composer install - 禁止任何
script里出现composer update,包括通过if判断分支名后自动执行的逻辑 - 若需更新依赖,走PR流程:改
composer.json→composer update --no-dev→ 提交新composer.lock
真正难处理的不是锁本身,而是锁住之后发现composer install依然卡住——那说明问题不在并发,而在PHP环境或平台约束不匹配。这时候flock再严也没用,得倒回去查php -v和composer show --platform的输出差在哪。










