即使具有完全打开的权限,PHP fopen() 也会对文件失败

2022-01-04 00:00:00 permissions php apache

我目前正在将我的 LAMP 从我的 Windows Server 迁移到运行 Debian 6 的 VPS.大多数一切正常,但是,其中一个 PHP 脚本未能写入其配置的日志文件.我不知道为什么,所以我写了一个新的、简单的、人为的 PHP 脚本来测试这个问题.

I'm currently migrating my LAMP from my Windows Server to a VPS running Debian 6. Most everything is working, however, one of the PHP scripts was failing to write to its configured log file. I could not determine why, so I wrote a new, simple, contrived PHP script to test the problem.

<?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;
        }
?>

然而,它失败了:

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 

  • 虽然我通常不会这样做,但为了帮助诊断,我将 /var/log/apache2/writetest/writetest.log 设置为 chmod 777.
  • 目录和文件都归www-data:www-data所有.
  • 该文件是使用 touch 创建的.
    • While I would never do it normally, to help diagnose, I set /var/log/apache2/writetest/writetest.log to chmod 777.
    • Both the directory and the file are owned by www-data:www-data.
    • The file was created with touch.
    • 我运行 strace 来验证哪个进程正在执行打开:

      I ran strace to verify which process was performing the 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)
      

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

      I checked and pid 21931 was indeed one of the apache2 child processes running under www-data. As you can see, I also included echo exec('whoami'); in the script which confirmed the script was being run by 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 (file): -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 并重启服务器
      • PHP is not running in safe mode
      • PHP open_basedir is not set
      • Version info: 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
      • This is on a VPS running under OpenVZ
      • ls -l (file): -rwxrwxrwx 1 www-data www-data 0 Sep 8 18:13 writetest.log
      • ls -l (directory): drwxr-xr-x 2 www-data www-data 4096 Sep 8 18:13 writetest
      • Apache2's parent process runs under root, and the child processes under www-data
      • selinux is not installed (thanks to Fabio for reminding me to mention this)
      • I have restarted apache many times and rebooted the server as well

      推荐答案

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

      Remember that in order to reach a file, ALL parent directories must be readable by www-data. You strace output seems to indicate that even accessing /var/log/apache2/writetest is failing. Make sure that www-data has permissions on the following directories:

      • /(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-)

相关文章