答案是目录属主被sudo污染为root,应根据报错路径用ls -ld确认归属,再执行sudo chown -R $USER:$USER修复所有权,禁用chmod -R 777。

根本不是权限位(rwx)不够,而是目录属主被 sudo composer install 污染成 root,当前用户无权写入——修复必须用 chown 归还所有权,禁用 chmod -R 777。
看报错路径,直接锁定问题目录
终端里那行带完整路径的错误就是线索,别被 “Permission denied” 四个字带偏:
-
file_put_contents(/home/alex/myapp/vendor/autoload.php)→ 问题在vendor/ -
Could not write to /var/www/myapp/composer.lock→ 问题在composer.lock -
Writing cache file ~/.composer/cache/repo/https---packagist.org/→ 问题在全局缓存目录
立刻执行这三行查归属:
ls -ld vendor/ ls -ld composer.lock ls -ld $(composer config --global cache-dir)
只要任意一行输出第三列是 root(比如 drwxr-xr-x 12 root root),就确认是所有权错配。
用 chown 修复,不是 chmod
chmod 控制“能不能读写”,chown 才决定“这东西归不归你”。误用 chmod -R 777 会触发 CI 拒收、Git 提示 ownership changed、后续 composer update 半途失败等连锁反应。
- 修复项目内目录:
sudo chown -R $USER:$USER vendor/ composer.lock - 修复全局缓存:
sudo chown -R $USER:$USER $(composer config --global cache-dir) - 整个
~/.composer都属root?直接重置:sudo chown -R $USER:$USER ~/.composer
sudo 这里只用于临时提权跑 chown,绝不是让你去跑 sudo composer install——后者才是污染源头。
Docker、CI 和 global require 的隐性坑
这些场景下权限问题常不报在主流程,但一样卡住:
- Docker 中宿主机 UID 是 1000,容器却以 UID 0(
root)运行 → 挂载卷时加user:1000或 Dockerfile 里加USER 1001 -
composer global require报错?先查composer config --global home,如果输出是/root/.composer或/var/www/.composer,说明环境已被污染 - 插件干扰:加
--no-plugins --no-interaction试试,composer install --no-plugins成功,大概率是某个全局插件(比如hirak/prestissimo)在/tmp创建 socket 后没释放权限
嵌套权限混乱最容易被忽略
一次 sudo composer install 可能让 vendor/ 下混进个别 root 所有子目录,ls -la vendor/ 就能发现。这时候别硬修,直接 rm -rf vendor/ 再重装更省事——前提是确认当前用户对项目根目录有写权限,且没被 COMPOSER_VENDOR_DIR 锁死到系统级路径。


















