Laravel 7 在 macOS 下必须确保 PHP 进程(如 Valet 的 _www 用户)对 storage 和 bootstrap/cache 可写,否则日志、缓存、队列、上传均失败;需执行 sudo chown -R $USER:_www storage bootstrap/cache、sudo chmod -R 775 和 sudo chmod g+s,并验证 touch storage/test 成功。

Mac 下 Laravel 7 的文件系统权限不是“设置”出来的,而是必须让 PHP 进程(php artisan serve 或 Nginx+PHP-FPM)能写入 storage 和 bootstrap/cache 目录——否则日志写不进、缓存生成失败、队列卡死、上传报错,全是 Permission denied。
为什么 storage 目录写不进去
Laravel 7 默认用 php artisan serve 启动时,PHP 是以当前用户身份运行的;但一旦换成 Nginx + PHP-FPM(比如用 Valet 或自己配 Nginx),实际写文件的是 www-data 或 _www 用户。macOS 默认不允许跨用户写入,且 SIP 可能拦截某些路径(如 /usr 下的符号链接)。
- 常见错误:
file_put_contents(/path/to/storage/logs/laravel.log): failed to open stream: Permission denied - 即使
ls -l storage看起来有写权限,也可能因属组不匹配或 SIP 阻断而失败 -
chmod -R 777 storage能临时绕过,但会触发 Gatekeeper 报警,且不解决根本问题
修复 storage 和 bootstrap/cache 权限(Mac + Valet / artisan serve)
你得先确认 PHP 进程是谁在跑:如果用 php artisan serve,就是你自己;如果用 Valet(绝大多数 Mac 开发者用它),Nginx 用的是 _www 用户,PHP-FPM 也默认跑在 _www 下。
- 执行:
sudo chown -R $USER:_www storage bootstrap/cache - 设权限:
sudo chmod -R 775 storage bootstrap/cache - 关键一步:让新创建的子目录继承组写权限:
sudo chmod g+s storage bootstrap/cache - 验证:
touch storage/test && rm storage/test—— 不报错才算成功
public/storage 符号链接失效怎么办
php artisan storage:link 在 macOS 上容易失败,不是命令错了,而是目标路径被 SIP 保护或已有残留链接。
- 先删旧链接:
rm public/storage - 再重试:
php artisan storage:link - 检查结果:
ls -l public/storage应输出public/storage -> ../storage/app/public - 如果仍提示 “The link already exists.” 却无法访问上传文件,说明链接指向了错误路径或目标目录不存在——手动创建:
mkdir -p storage/app/public
别碰 .env 和 config:cache 的权限陷阱
.env 文件必须对 Web 进程**不可读**(否则泄露数据库密码),但对 CLI 进程必须可读;config:cache 又要求 bootstrap/cache/config.php 可写——这两个需求天然冲突,尤其在 Valet 下。
- 确保
.env权限是600:chmod 600 .env - 不要用
sudo php artisan config:cache,这会让缓存文件属主变成 root,后续php artisan serve就写不了日志 - 正确做法:清空缓存用普通用户执行:
php artisan config:clear && php artisan cache:clear - 如果已用 sudo 缓存过,先
sudo rm bootstrap/cache/config.php,再用当前用户重生成
最常被忽略的点:Mac 上的 _www 组和 staff 组不是一回事,硬把 storage 归给 $USER:staff 看似能 touch 成功,但 Valet 的 PHP-FPM 仍会因组权限不匹配写失败——必须显式用 _www 作为组名,且确保该组存在(dscl . -list /Groups | grep _www)。


















