PHP脚本无法写入目录求助:CLI正常但浏览器访问失败
看起来你遇到的是典型的「命令行环境和Web服务器环境权限/限制不一致」的问题——命令行跑没问题,但apache作为Web用户跑就失败,哪怕文件系统权限设到777都不行,最常见的元凶是SELinux,其次是PHP的open_basedir限制,我给你一步步拆解:
1. 先排查SELinux(90%的概率是这个)
CentOS/RHEL这类系统默认开启SELinux,它是一套独立于文件系统权限的强制访问控制系统。哪怕你把目录所有权设给apache、权限开777,只要SELinux没允许apache往这个目录写,就会报错。
快速验证:
临时关闭SELinux测试(重启后会恢复默认):
setenforce 0
然后刷新浏览器访问你的脚本,如果能成功写入文件,那实锤是SELinux的问题。
永久修复:
给templates_c目录设置正确的SELinux上下文,让apache拥有写入权限:
# 临时生效,重启后可能丢失 chcon -R -t httpd_sys_rw_content_t /var/www/html/***/templates_c/ # 永久生效(需要先安装policycoreutils-python包) semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/***/templates_c(/.*)?" restorecon -Rv /var/www/html/***/templates_c/
2. 检查PHP的open_basedir限制
如果SELinux没问题,那可能是PHP的open_basedir配置限制了apache用户能访问的目录范围。这个配置会把PHP的文件操作限制在指定的目录列表里,超出的话直接拒绝。
验证方法:
在你的脚本开头加一行,输出当前的open_basedir配置:
<?php echo "open_basedir: " . ini_get('open_basedir'); // 下面是你的原脚本内容 $myfile = fopen("/var/www/html/***/templates_c/testnewfile.txt", "w") or die("Unable to open file!"); $txt = "John Doe\n"; fwrite($myfile, $txt); $txt = "Jane Doe\n"; fwrite($myfile, $txt); fclose($myfile); ?>
如果输出里没有包含/var/www/html/***/templates_c的上级目录,就需要修改php.ini(或者你的虚拟主机配置文件),把该路径添加到open_basedir里,然后重启apache服务。
3. 最后排查路径一致性问题
虽然你用的是绝对路径,但也有可能是符号链接解析差异,或者命令行和Web环境的路径解析不同。可以在脚本里输出当前工作目录对比:
<?php echo "Current working directory: " . getcwd(); // 原脚本内容 ?>
如果浏览器输出的工作目录和你命令行运行pwd的结果不一样,可能需要调整路径为相对DOCUMENT_ROOT的路径,或者确保绝对路径完全正确。
为什么命令行正常但浏览器不行?
核心原因是:命令行运行PHP时,用的是你SSH登录用户的权限、环境变量和安全策略;而浏览器访问时,PHP是以apache用户身份运行的,受apache的安全限制(SELinux、open_basedir等),这两个环境的规则完全不同。
内容的提问来源于stack exchange,提问作者Rick Roy

