nginx php permission denied
nginx的error.log里刷出“Permission denied”的时候,十有八九不是nginx本身的问题,而是php-fpm的工作进程没权限去读那个文件或者目录。我见过太多人第一反应去改nginx.conf的user指令,折腾半天没用——因为真正干活的进程是php-fpm,不是nginx。 拿个实际例子说吧。有一次部署一个laravel项目,静态文件访问正常,一到php路由就报404,打开日志一看: 排查到最后才发现,问题出在php-fpm的socket文件上。php-fpm监听的是 还有一种常见情况是日志文件本身。php-fpm的slow log或者error log路径写到了某个只有root能写的目录,比如 再一个坑是selinux。如果你用的是centos或者rocky,先别急着改权限。执行 排查顺序建议这样来:先看nginx日志里具体报错的文件路径,然后 别动不动就chmod 777,那是给自己埋雷。正确做法是让php-fpm的worker进程和文件属主保持一致,或者用acl精确控制。比如2024/03/15 10:23:45 [crit] 12345#0: *678 open() "/var/www/html/public/index.php" failed (13: Permission denied)。当时nginx的worker进程跑在www-data用户下,php-fpm也跑在www-data下,目录权限是755,文件是644,按理说没问题。但就是报错。/run/php/php8.1-fpm.sock,这个socket文件的属主是www-data,但nginx访问的时候用的用户也是www-data,看起来没问题对吧?可实际上,nginx和php-fpm之间通信走的是socket,如果socket文件的父目录/run/php权限是700,那nginx进程根本进不去这个目录——即使socket文件本身权限是777也没用。Linux的权限检查是逐级目录的,中间任何一层卡住,后面全白搭。/var/log/php。你chmod 777那个日志文件,但如果/var/log/php目录的权限是750且属主是root,php-fpm的worker进程照样写不进去。这时候错误日志里会显示open() "/var/log/php/error.log" failed (13: Permission denied),但很多人只盯着业务代码文件看,忽略了日志文件自己都写不进去。getenforce看看是不是Enforcing。selinux会无视常规的rwx权限,直接按自己的策略拦截。我就见过一个案例,nginx和php-fpm的权限完全正确,但selinux拦截了php-fpm对某个目录的读取。解决办法要么是setsebool -P httpd_can_network_connect 1,要么直接chcon -R -t httpd_sys_content_t /var/www/html。如果你不想折腾selinux,直接setenforce 0临时关闭测试,确认是它的问题后再做永久策略。ls -l那个文件确认属主和权限。接着用sudo -u www-data cat /path/to/file模拟php-fpm用户读取,如果读不了就调整。如果文件能读但还报错,检查所有父目录的x权限(执行权限)是否对www-data开放。最后再看socket文件和selinux。这套流程走下来,90%的permission denied都能解决。setfacl -R -m u:www-data:rx /var/www/html,比粗暴改权限干净得多。记住,permission denied的本质是“进程身份”和“文件身份”不匹配,搞清楚你跑的进程是哪个用户,比瞎试命令有用一百倍。