500错误主因是Web服务器进程无权执行PHP文件:mod_php只需文件644+目录755,php-fpm还需目录x权限;须匹配www-data等运行用户、SELinux/AppArmor上下文及php-fpm pool配置。

chmod 后 500 错误:常见权限组合陷阱
PHP 脚本执行失败,不是因为文件没读权限,而是 Web 服务器(如 Apache 或 Nginx)启动的 worker 进程无法执行它。典型表现是访问页面返回 500 Internal Server Error,且错误日志里出现类似 Permission denied: exec of '/var/www/html/index.php' failed 的提示。
关键点在于:PHP 文件本身不需要 x(执行)权限;但若用的是 mod_php(Apache 模块模式),只需 r(读)权限;而如果用的是 php-fpm(FastCGI 模式),则 PHP 解释器进程需对文件有读权限,对所在目录有执行(x)权限——否则无法 chdir 进入目录或打开文件。
-
index.php应设为644(所有者可读写,组/其他仅读) - 其父目录(如
/var/www/html)必须有x权限,即至少755(所有者读写执行,组/其他读执行) - 切勿对 PHP 文件设
755—— 不安全,且在某些 SELinux 或严格 umask 下反而触发拒绝
www-data / nginx 用户 vs 文件所有者不匹配
修改权限后仍 403 或 500,大概率是 Web 服务进程运行用户(如 www-data、nginx 或 apache)与文件所有者不一致,且组权限或其它权限未开放。
先确认当前 Web 服务运行用户:
立即学习“PHP免费学习笔记(深入)”;
ps aux | grep -E '(apache|httpd|nginx|php-fpm)'
再检查文件归属和权限:
ls -l /var/www/html/index.php
- 若输出显示
-rw-r--r-- 1 root root ...,而 Web 进程是www-data,那它只能靠“other”位读取,此时644可行;但若你误设成640,就彻底拒绝了 - 更稳妥做法:把文件属组改为
www-data,并启用组读权限,例如chown :www-data /var/www/html/index.php && chmod 640 /var/www/html/index.php - 目录同理:
chown :www-data /var/www/html && chmod 750 /var/www/html
SELinux 或 AppArmor 干预导致“权限正确却拒绝访问”
在 CentOS/RHEL(启用 SELinux)或 Ubuntu(启用 AppArmor)上,即使 chmod 和 chown 全部正确,仍可能被内核强制策略拦截。典型现象:错误日志无明确权限提示,curl -I 返回 403,ls -Z 显示上下文异常。
- 检查 SELinux 状态:
sestatus;临时放行测试:setenforce 0(别长期关闭) - 查看拒绝记录:
ausearch -m avc -ts recent | grep httpd或dmesg | grep avc - 修复上下文(推荐):
restorecon -Rv /var/www/html;或手动赋值:chcon -t httpd_sys_content_t /var/www/html/ - AppArmor 用户查:
aa-status,日志在/var/log/audit/audit.log或/var/log/syslog
php-fpm pool 用户配置覆盖文件系统权限
使用 php-fpm 时,www.conf 中的 user 和 group 设置(如 user = www-data)决定了 PHP 进程实际身份。这个身份必须能读取脚本、写入 session 目录、访问数据库 socket 等——文件系统权限只是基础,不是全部。
- 检查 pool 配置:
grep -E '^(user|group|listen.owner)' /etc/php/*/fpm/pool.d/www.conf - 确保
listen.owner和listen.group对应的 Unix socket 文件(如/run/php/php8.1-fpm.sock)权限匹配,否则 Nginx 会报connect() to unix:/run/php/php8.1-fpm.sock failed - session.save_path 目录(如
/var/lib/php/sessions)必须对该user可写,否则登录态失效,看似“无法访问”
权限问题从来不是孤立的 chmod 操作,而是用户、组、上下文、服务配置四层叠加的结果。漏掉任意一层,都可能让 644 变成摆设。











