
在 centos 7 上,即使 `/var/www/html` 目录已正确设置为 `apache` 用户所有且权限为 `775`,php 脚本调用 `file_put_contents()` 仍可能因 selinux 策略限制而报 “permission denied”,需通过 `chcon` 或 `semanage` 配置 httpd 可写上下文。
在 CentOS 7 默认安装中,SELinux 处于 enforcing 模式,它不仅检查传统 Unix 权限(user/group/other + rwx),还强制执行安全上下文(Security Context)策略。Apache(即 httpd 进程)默认只能读取标记为 httpd_sys_content_t 的文件,写入操作必须显式授予 httpd_sys_rw_content_t 上下文——这是导致 file_put_contents() 报错 Permission denied 的根本原因,与文件属主或 775 权限无关。
✅ 正确解决步骤(推荐持久化方案)
-
确认 SELinux 状态
sestatus # 输出应为:enabled + enforcing
-
临时验证是否为 SELinux 导致(仅调试)
sudo setenforce 0 # 切换到 permissive 模式(不生效策略,但记录日志) # 再运行 PHP 脚本,若成功,则确认是 SELinux 问题 sudo setenforce 1 # 恢复 enforcing 模式(切勿长期禁用!)
-
永久修复:为目录分配可写上下文
立即学习“PHP免费学习笔记(深入)”;
# 方式一(适用于单路径,立即生效): sudo chcon -R -t httpd_sys_rw_content_t /var/www/html/ # 方式二(推荐:持久化,重启后仍有效): sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html(/.*)?" sudo restorecon -Rv /var/www/html/
? semanage fcontext 定义规则,restorecon 应用规则并递归修正上下文。(/.*)? 表示匹配该路径及其全部子目录/文件。
-
验证上下文是否更新
ls -Z /var/www/html/ # 正确输出应包含:system_u:object_r:httpd_sys_rw_content_t:s0
? 测试代码(建议保存为 /var/www/html/test_write.php)
";
echo "File permissions: " . substr(sprintf('%o', fileperms($file)), -4) . "
";
echo "Owner: " . fileowner($file) . " (uid), " . filegroup($file) . " (gid)";
} else {
echo "❌ Failed: Permission denied. Check SELinux context.";
}
?>⚠️ 注意事项
- 切勿使用 chmod 777 或 setenforce 0 作为生产环境解决方案:前者破坏最小权限原则,后者完全关闭安全防护。
- 若应用需写入特定子目录(如 storage/、uploads/),请仅对该子目录授予权限,而非整个 /var/www/html/:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/uploads(/.*)?" sudo restorecon -Rv /var/www/html/uploads
- SELinux 日志位于 /var/log/audit/audit.log,可用 ausearch -m avc -ts recent | audit2why 分析拒绝原因。
- 若 semanage 命令不存在,请先安装策略管理工具:sudo yum install policycoreutils-python-utils。
通过上述配置,PHP 进程即可在符合安全策略的前提下,安全、稳定地执行文件写入操作——既满足功能需求,又坚守企业级服务器的安全基线。











