根本原因是Web服务器与CLI用户不一致导致文件属主/权限错乱;正确做法是让两者同属一个组(如www-data),设置组写权限和setgid,并清理旧缓存后执行cache:clear。

为什么 var/cache 突然变只读?
根本原因不是 Symfony 本身,而是 Web 服务器(如 Apache/Nginx)和 CLI 用户不一致导致的文件属主/权限错乱。比如你用 php bin/console cache:clear 以自己的用户执行,生成的缓存文件属主是你的账号;但 Web 请求由 www-data 或 nginx 用户发起,它没权限写入这些文件。
cache:clear 报 Permission denied 怎么修?
别直接 chmod 777 var/cache —— 这治标不治本,还埋下安全风险。正确做法是让两个运行环境共用一个组,并赋予组写权限:
- 确认 Web 服务器用户(如
www-data)和当前 CLI 用户同属一个组,例如www-data - 把当前用户加进该组:
sudo usermod -a -G www-data $USER,然后重新登录终端 - 设好目录属组和 setgid(确保新文件继承组):
sudo chgrp -R www-data var/cache var/log+sudo chmod -R g+rw var/cache var/log+sudo chmod g+s var/cache var/log - 清空缓存前先删掉旧文件:
rm -rf var/cache/*,再跑php bin/console cache:clear --no-warmup
开发环境用 APCu 或 filesystem 驱动时权限还重要吗?
仍然重要。即使你配了 adapter: filesystem,Symfony 默认仍会尝试在 var/cache 下写代理类、容器缓存等 PHP 文件。APCu 虽不依赖磁盘,但启动阶段仍需生成并写入 var/cache/dev/App_KernelDevDebugContainer.php 这类文件 —— 它们全落在 var/cache 里。
所以只要没关掉「缓存写入」,就绕不开目录权限。唯一跳过它的办法是:在开发环境强制禁用所有缓存写入(不推荐),或改用 NullAdapter(仅用于极端调试)。
Docker 环境下 var/cache 权限更难搞?
是的,因为容器内用户 ID(UID/GID)和宿主机不匹配。常见错误是直接挂载宿主机 var/cache 目录进去,结果容器里用 UID=82 的 www-data 去写宿主机上属于 UID=1000 的目录,必然失败。
- 方案一:构建镜像时指定 UID/GID 一致,比如
RUN groupmod -g 1000 www-data && usermod -u 1000 www-data - 方案二:挂载时用命名卷(named volume),让 Docker 自动处理属主,再通过
docker exec进容器手动chown -R www-data:www-data /var/www/html/var/cache - 方案三:启动容器时用
--user $(id -u):$(id -g)强制对齐(适合本地开发)
真正麻烦的不是操作步骤,而是每次 cache:clear 后,Docker 卷里文件的属主可能又变成 root —— 这时候得再进容器 chown 一次,或者写个 wrapper 脚本自动做。










