答案是因之前执行sudo composer update导致vendor/属主变为root,应运行sudo chown -r $user:$user vendor/修复所有权,切勿用chmod 777或重复sudo。

composer update 后 vendor/ 下文件属主变成 root
这是最典型的“权限污染”现象:你之前执行过 sudo composer update,导致新生成的 vendor/ 子目录和文件全部归 root 所有。后续普通用户运行 composer dump-autoload 或 php artisan optimize 时就会卡在 file_put_contents(.../autoload.php) 上。
修复只需一步,但必须精准:
- 先确认问题范围:
ls -ld vendor/—— 如果输出第一列是root,就对了 - 只修复
vendor/目录本身及其内容:sudo chown -R $USER:$USER vendor/ - 别碰
composer.lock—— 它只是文本文件,只要可读就行;如果也被改成了root,一并加进命令:sudo chown -R $USER:$USER vendor/ composer.lock
更新后 storage/ 或 bootstrap/cache/ 写入失败(Laravel 场景)
composer update 本身不碰框架的 runtime 目录,但如果你同时跑了 php artisan config:clear 或 php artisan view:clear,这些命令会尝试写入 storage/ 和 bootstrap/cache/。此时若 CLI 用户和 Web 服务器用户不同(比如你是 alex,Nginx 是 www-data),就会报 Permission denied。
关键不是让所有目录都归你,而是让两者能协作:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 把当前用户加进 Web 组:
sudo usermod -a -G www-data $USER - 把 runtime 目录组设为
www-data:sudo chgrp -R www-data storage bootstrap/cache - 开放组写权限:
sudo chmod -R g+w storage bootstrap/cache - 确保 umask 不干扰(在 shell 配置中加:
umask 002)
全局依赖更新后 laravel 命令突然找不到
执行 composer global update 后,laravel 或 phpunit 命令失效,常见于两种情况:
-
~/.composer/vendor/bin/下的二进制文件被覆盖或权限重置 —— 检查:ls -l ~/.composer/vendor/bin/laravel,若权限不是-rwxr-xr-x,补上:chmod +x ~/.composer/vendor/bin/laravel - 更隐蔽的是:
COMPOSER_HOME被意外指向了/root/.composer—— 运行composer config --global home确认路径;如果是/root/.composer,说明之前用过sudo composer global update,得立刻清理:sudo rm -rf /root/.composer,再重装 - 别忘了 PATH 是否还包含该目录:
echo $PATH | grep composer,缺失就补:export PATH="$HOME/.composer/vendor/bin:$PATH"
Docker 或 CI 中 vendor/ 权限随每次 update 变化
本地没问题,CI 流水线里每次 composer update 后 vendor/ 属主变成 root 或 UID 0?根本原因是构建镜像时用了 USER root,或 GitHub Actions 默认以 runner 用户运行但挂载卷的宿主机目录属主是 UID 1001。
务实解法不是硬改权限,而是统一 UID:
- Dockerfile 开头显式创建非 root 用户:
RUN addgroup -g 1001 -f www && adduser -S runner -u 1001,然后USER runner - GitHub Actions 中,在 job 步骤开头加:
run: sudo chown -R ${{ github.actor }}:$(id -gn) vendor/ - 终极保险:CI 脚本里删掉
vendor/再重装,避免继承脏状态 ——rm -rf vendor/ && composer install --no-interaction
权限变化从来不是 Composer 的 bug,而是所有权在多个上下文间流转时没被显式对齐。每次 update 都是一次所有权重置点,盯住 whoami、ls -ld、composer config --global home 这三件事,比任何 chmod 都管用。










