即使具有广泛的权限,PHP fopen()也会在文件上失败

Gre*_*ski 9 php apache permissions

我正在将我的LAMP从我的Windows服务器迁移到运行Debian 6的VPS.大多数工作都正常,但是,其中一个PHP脚本无法写入其配置的日志文件.我无法确定原因,所以我写了一个新的,简单的,有人工作的PHP脚本来测试问题.

<?php
        ini_set('display_errors', 1);
        error_reporting(E_ALL);
        echo exec('whoami');
        $log = fopen('/var/log/apache2/writetest/writetest.log', 'a');
        if ($log != NULL)
        {
                fflush($log);
                fclose($log);
                $log = NULL;
        }
?>
Run Code Online (Sandbox Code Playgroud)

但是,结果失败了:

www-data Warning: fopen(/var/log/apache2/writetest/writetest.log): failed to open stream: Permission denied in /var/www/_admin/phpwritetest.php on line 5 
Run Code Online (Sandbox Code Playgroud)
  • 虽然我永远不会这样做,但为了帮助诊断,我设置/var/log/apache2/writetest/writetest.log为chmod 777.
  • 目录和文件都归www-data:www-data.
  • 该文件是用touch.创建的.

我跑来strace验证哪个进程正在执行open:

[pid 21931] lstat("/var/log/apache2/writetest/writetest.log", 0x7fff81677d30) = -1 EACCES (Permission denied)
[pid 21931] lstat("/var/log/apache2/writetest", 0x7fff81677b90) = -1 EACCES (Permission denied)
[pid 21931] open("/var/log/apache2/writetest/writetest.log", O_RDWR|O_CREAT|O_TRUNC, 0666) = -1 EACCES (Permission denied)
Run Code Online (Sandbox Code Playgroud)

我检查过,pid 21931确实是运行在其下的apache2子进程之一www-data.正如您所看到的,我还在echo exec('whoami');脚本中包含了确认脚本正在运行的脚本www-data.

其他说明:

  • PHP未在安全模式下运行
  • PHP open_basedir没有设置
  • 版本信息: Apache/2.2.16 (Debian) PHP/5.3.3-7+squeeze3 with Suhosin-Patch mod_ssl/2.2.16 OpenSSL/0.9.8o
  • uname -a: 2.6.32-238.19.1.el5.028stab092.2 #1 SMP Thu Jul 21 19:23:22 MSD 2011 x86_64 GNU/Linux
  • 这是在OpenVZ下运行的VPS上
  • ls -l(文件): -rwxrwxrwx 1 www-data www-data 0 Sep 8 18:13 writetest.log
  • ls -l(目录): drwxr-xr-x 2 www-data www-data 4096 Sep 8 18:13 writetest
  • Apache2的父进程在其下运行root,子进程在其下运行www-data
  • 未安装selinux(感谢Fabio提醒我提及此问题)
  • 我已多次重启apache并重启服务器

Chr*_*rle 13

请记住,为了访问文件,所有父目录必须是www-data可读的.strace输出似乎表明即使访问 /var/log/apache2/writetest失败也是如此.确保www-data具有以下目录的权限:

  • / (r-x)
  • /var (r-x)
  • /var/log (r-x)
  • /var/log/apache2 (r-x)
  • /var/log/apache2/writetest (rwx)
  • /var/log/apache2/writetest/writetest.log (rw-)