jsonfile驱动不保证原子写入,失败会留下破损文件;它仅对写入加锁,无跨文件事务或回滚能力,也不校验写入后json完整性、不备份原文件、不采用rename原子切换。

JsonFile驱动不保证原子写入,失败就留半截文件
Composer 的 JsonFile 类(如用于读写 composer.json 和 composer.lock)底层用的是 file_put_contents($path, $content, LOCK_EX),但它只对写入过程加锁,**不提供跨文件事务或回滚能力**。这意味着:如果写 composer.lock 时磁盘满、权限被拒或进程被 kill,你很可能得到一个 JSON 语法错误的破损文件——开头是合法 JSON,结尾突然中断。
常见现象:composer install 报错 JSON decode error: Syntax error,但 composer.json 没动,composer.lock 却已损坏;或者 composer update 中断后,vendor/ 里混着新旧包,composer.lock 里哈希对不上。
-
JsonFile::write()不校验写入后文件是否完整可解析,只管写完就返回 - 它不备份原文件,也不做 rename 原子切换(不像
git commit先写 object 再更新 ref) - 即使加了
LOCK_EX,也防不住外部进程直接rm或mv目标文件
为什么不能靠 --dry-run 防住 lock 文件损坏
--dry-run 只模拟依赖解析和下载计划,**完全不触碰 composer.lock 文件**。它不会生成新 lock 内容,更不会尝试写入。所以它能告诉你“这次 update 会装哪些包”,但无法提前暴露 lock 文件本身是否可写、磁盘是否够、权限是否正确。
真正危险的操作发生在 composer update 执行末尾:依赖求解成功 → 下载完成 → 开始序列化新 lock 内容 → 调用 JsonFile::write() → 失败 → 留下坏 lock。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- CI 环境里常见陷阱:
composer update --dry-run过了,接着跑composer update却因/tmp满失败,lock 已毁 -
--dry-run不检查 vendor 目录是否可写,也不校验现有 lock 是否语法合法(损坏的 lock 仍可能被读取并用于 install) - 想验证 lock 可写性?得手动
php -r "file_put_contents('composer.lock', json_encode(['foo'=>'bar'], JSON_UNESCAPED_UNICODE), LOCK_EX);"
生产环境必须绕开 JsonFile 直接写入
别指望 Composer 自身修复这个问题。所有稳定上线的 PHP 项目,都应放弃在生产机上直接跑 composer install,改用「构建机生成 + 原子切换」流程。核心是:让 JsonFile 的写操作只发生在隔离、可控的构建环境里,线上只做 mv 切换。
- 构建阶段:在干净 Docker 容器里运行
composer install --no-dev --optimize-autoloader,输出完整vendor/和composer.lock - 部署阶段:把构建产物整体 tar 包上传,解压到新路径(如
/var/www/app-202607061200),再用ln -sfn切换软链指向当前版本 - 绝不在线上执行
composer update或任何修改composer.lock的命令 - 若真要热更新,用
composer require --no-update改composer.json,再走完整构建流程,而不是跳过 lock 校验
autoload_files 写错路径也不会报错,但函数就永远找不到
autoload.files 是 Composer 唯一支持函数自动加载的机制,但它由 JsonFile 驱动读取,而读取失败时 Composer **静默忽略**该字段——既不报错,也不提示路径不存在。结果就是:你写了 "src/helpers.php",实际文件在 "app/helpers.php",dump-autoload 后 vendor/composer/autoload_files.php 里根本没这行,函数调用直接 Fatal error: Call to undefined function。
- 路径必须相对于
composer.json所在目录,不能用./或../混用(CI 中工作目录不可控) - 通配符
"src/*.php"在 Composer ≥ 2.2 支持,但匹配到非 PHP 文件(如src/.gitignore)会导致dump-autoload失败 - 改完
autoload.files后,必须显式运行composer dump-autoload,install或update不会自动触发 - 检查是否生效:打开
vendor/composer/autoload_files.php,确认路径已正确展开为绝对路径
JsonFile 的设计目标从来不是高可靠存储,而是轻量配置读写。它不处理并发冲突、不校验内容完整性、不提供重试或回滚。把它的行为当成“原子”来依赖,等于在生产环境埋雷。










